On Mon, Feb 19, 2018 at 09:43:32AM +0000, Ard Biesheuvel wrote: > This adds support for using the random number generator in the Atmel > AtSha204a over I2C. Other functionality of the chip is currently > unsupported. > > Note that the the I2C support in this device essentially violates the > protocol layering, by requiring that the device is woken up by driving > SDA low for a certain amount of time, which is something that cannot be > expressed in terms of an I2C packet sent to the device's slave address. > Instead, the slave address 0x0 is added to the device's address array, > and the wake is sent by sending a dummy write to address 0x0, and > ignoring the subsequent error. This requires the I2C bus to be clocked > at 100 kHz.
As long as the violation is down to the component rather than its integration onto the mezzanine board, I see no problem with this. > Contributed-under: TianoCore Contribution Agreement 1.1 > Signed-off-by: Ard Biesheuvel <[email protected]> > --- > Silicon/Atmel/AtSha204a/AtSha204a.dec | 22 ++ > Silicon/Atmel/AtSha204a/AtSha204aDriver.c | 308 ++++++++++++++++++++ > Silicon/Atmel/AtSha204a/AtSha204aDriver.h | 81 +++++ > Silicon/Atmel/AtSha204a/AtSha204aDxe.inf | 52 ++++ > Silicon/Atmel/AtSha204a/ComponentName.c | 186 ++++++++++++ > Silicon/Atmel/AtSha204a/DriverBinding.c | 242 +++++++++++++++ > 6 files changed, 891 insertions(+) > > diff --git a/Silicon/Atmel/AtSha204a/AtSha204a.dec > b/Silicon/Atmel/AtSha204a/AtSha204a.dec > new file mode 100644 > index 000000000000..f1fdea59843d > --- /dev/null > +++ b/Silicon/Atmel/AtSha204a/AtSha204a.dec > @@ -0,0 +1,22 @@ > +## @file > +# > +# Copyright (c) 2018, Linaro Ltd. All rights reserved. > +# > +# This program and the accompanying materials > +# are licensed and made available under the terms and conditions of the BSD > License > +# which accompanies this distribution. The full text of the license may be > found at > +# http://opensource.org/licenses/bsd-license.php > +# > +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, > +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR > IMPLIED. > +# > +## > + > +[Defines] > + DEC_SPECIFICATION = 0x0001001A > + PACKAGE_NAME = AtSha204a > + PACKAGE_GUID = 86085a5b-355b-4e72-92ab-fc3e1d71c9ad > + PACKAGE_VERSION = 0.1 > + > +[Guids] > + gAtSha204aI2cDeviceGuid = { 0x52e9b64b, 0x4ec1, 0x4bd6, { 0x9e, 0x1c, > 0x6d, 0xac, 0xef, 0x35, 0x18, 0x21 } } > diff --git a/Silicon/Atmel/AtSha204a/AtSha204aDriver.c > b/Silicon/Atmel/AtSha204a/AtSha204aDriver.c > new file mode 100644 > index 000000000000..25329086592a > --- /dev/null > +++ b/Silicon/Atmel/AtSha204a/AtSha204aDriver.c > @@ -0,0 +1,308 @@ > +/** @file > + Device driver for the Atmel ATSHA204A random number generator. > + > + Copyright (c) 2018, Linaro Ltd. All rights reserved.<BR> > + > + This program and the accompanying materials > + are licensed and made available under the terms and conditions of the BSD > + License which accompanies this distribution. The full text of the license > may > + be found at http://opensource.org/licenses/bsd-license.php. > + > + 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 "AtSha204aDriver.h" > + > +#include <Library/BaseMemoryLib.h> > +#include <Library/DebugLib.h> > +#include <Library/MemoryAllocationLib.h> > + > +#define MAX_RETRIES 5 > + > +// Don't bother calculating the CRC for the immutable RANDOM opcode packet > +#define OPCODE_COMMAND_PACKET_CRC 0xcd24 > + > +/** > + Returns information about the random number generation implementation. > + > + @param[in] This A pointer to the EFI_RNG_PROTOCOL > instance. > + @param[in,out] AlgorithmListSize On input, the size in bytes of > AlgorithmList > + On output with a return code of > EFI_SUCCESS, > + the size in bytes of the data returned in > + AlgorithmList. On output with a return > + code of EFI_BUFFER_TOO_SMALL, the size of > + AlgorithmList required to obtain the > list. > + @param[out] AlgorithmList A caller-allocated memory buffer filled > by > + the driver with one EFI_RNG_ALGORITHM > + element for each supported RNG algorithm. > + The list must not change across multiple > + calls to the same driver. The first > + algorithm in the list is the default > + algorithm for the driver. > + > + @retval EFI_SUCCESS The RNG algorithm list was returned > + successfully. > + @retval EFI_UNSUPPORTED The services is not supported by this > driver > + @retval EFI_DEVICE_ERROR The list of algorithms could not be > + retrieved due to a hardware or firmware > + error. > + @retval EFI_INVALID_PARAMETER One or more of the parameters are > incorrect. > + @retval EFI_BUFFER_TOO_SMALL The buffer RNGAlgorithmList is too small > to > + hold the result. > + > +**/ > +STATIC > +EFI_STATUS > +EFIAPI > +AtSha240aGetInfo ( > + IN EFI_RNG_PROTOCOL *This, > + IN OUT UINTN *AlgorithmListSize, > + OUT EFI_RNG_ALGORITHM *AlgorithmList > +) > +{ > + UINTN Size; > + > + // > + // We only implement the raw algorithm > + // > + Size = sizeof gEfiRngAlgorithmRaw; Use parantheses for sizeof? Also, can this be different from sizeof (EFI_GUID)? > + > + if (*AlgorithmListSize < Size) { > + *AlgorithmListSize = Size; > + return EFI_BUFFER_TOO_SMALL; > + } > + > + gBS->CopyMem (AlgorithmList, &gEfiRngAlgorithmRaw, Size); You already pull in BaseMemoryLib, so could use CopyGuid? > + *AlgorithmListSize = Size; > + > + return EFI_SUCCESS; > +} > + > + > +/** > + Produces and returns an RNG value using either the default or specified RNG > + algorithm. > + > + @param[in] This A pointer to the EFI_RNG_PROTOCOL instance. > + @param[in] Algorithm A pointer to the EFI_RNG_ALGORITHM that > + identifies the RNG algorithm to use. May be > + NULL in which case the function will use > its > + default RNG algorithm. > + @param[in] ValueLength The length in bytes of the memory buffer > + pointed to by RNGValue. The driver shall > + return exactly this numbers of bytes. > + @param[out] Value A caller-allocated memory buffer filled by > the > + driver with the resulting RNG value. > + > + @retval EFI_SUCCESS The RNG value was returned successfully. > + @retval EFI_UNSUPPORTED The algorithm specified by RNGAlgorithm is > not > + supported by this driver. > + @retval EFI_DEVICE_ERROR An RNG value could not be retrieved due to > a > + hardware or firmware error. > + @retval EFI_NOT_READY There is not enough random data available > to > + satisfy the length requested by > + RNGValueLength. > + @retval EFI_INVALID_PARAMETER RNGValue is NULL or RNGValueLength is zero. > + > +**/ > +STATIC > +EFI_STATUS > +EFIAPI > +AtSha240aGetRNG ( > + IN EFI_RNG_PROTOCOL *This, > + IN EFI_RNG_ALGORITHM *Algorithm OPTIONAL, > + IN UINTN ValueLength, > + OUT UINT8 *Value > +) > +{ > + EFI_STATUS Status; > + ATSHA204A_DEV *AtSha204a; > + ATSHA204A_I2C_RNG_COMMAND Cmd; > + ATSHA204A_I2C_RNG_RESULT Res; > + I2C_RNG_REQUEST Req; > + I2C_RNG_REQUEST Resp; Since I just gave Marcin a hard time over non-approved abbreviations, I should probably flag these too... Would you mind terribly turning them into Command, Result, Request, Response? > + UINTN Retries; > + > + if (Algorithm != NULL && !CompareGuid (Algorithm, &gEfiRngAlgorithmRaw)) { > + return EFI_UNSUPPORTED; > + } > + > + AtSha204a = ATSHA204A_DEV_FROM_THIS (This); > + > + Req.OperationCount = 1; > + Req.Operation.Flags = 0; > + > + Cmd.Command = ATSHA204A_COMMAND; > + Cmd.Count = sizeof (Cmd) - 1; > + Cmd.Opcode = ATSHA204A_OPCODE_RANDOM; > + Cmd.Param1 = 0; > + Cmd.Param2 = 0; > + Cmd.Crc = OPCODE_COMMAND_PACKET_CRC; > + > + Resp.OperationCount = 1; > + Resp.Operation.Flags = I2C_FLAG_READ; > + Resp.Operation.LengthInBytes = sizeof (Res); > + Resp.Operation.Buffer = (VOID *)&Res; > + > + Retries = 0; > + while (ValueLength > 0) { > + // > + // The AtSha204a will go back to sleep right in the middle of a > transaction > + // if it does not complete in ~1.3 seconds. So send the wake sequence for > + // each iteration, which consists of a dummy write to slave address 0x0. > + // > + Req.Operation.LengthInBytes = 0; > + Status = AtSha204a->I2cIo->QueueRequest (AtSha204a->I2cIo, 1, NULL, > + (VOID *)&Req, NULL); > + DEBUG ((DEBUG_INFO, "%a: wake AtSha204a: I2cIo->QueueRequest() - %r\n", > + __FUNCTION__, Status)); > + > + gBS->Stall (2500); // wait 2.5 ms for wake to complete > + > + Req.Operation.LengthInBytes = sizeof (Cmd); > + Req.Operation.Buffer = (VOID *)&Cmd; > + Status = AtSha204a->I2cIo->QueueRequest (AtSha204a->I2cIo, 0, NULL, > + (VOID *)&Req, NULL); > + if (EFI_ERROR (Status)) { > + if (++Retries <= MAX_RETRIES) { > + continue; > + } > + DEBUG ((DEBUG_ERROR, "%a: I2C request transfer failed, Status == %r\n", > + __FUNCTION__, Status)); > + return EFI_DEVICE_ERROR; > + } > + > + gBS->Stall (50 * 1000); // 50 ms max execution time for RANDOM opcode Is there no way of polling for response complete? 50ms per iteration?? :( (or, well, 52.5 in total) / Leif > + > + Status = AtSha204a->I2cIo->QueueRequest (AtSha204a->I2cIo, 0, NULL, > + (VOID *)&Resp, NULL); > + if (EFI_ERROR (Status)) { > + if (++Retries <= MAX_RETRIES) { > + continue; > + } > + DEBUG ((DEBUG_ERROR, "%a: I2C response transfer failed, Status == > %r\n", > + __FUNCTION__, Status)); > + return EFI_DEVICE_ERROR; > + } > + > + if (Res.Count < sizeof (Res)) { > + // > + // Incomplete packet received, most likely due to an error. Retry. > + // > + if (++Retries <= MAX_RETRIES) { > + continue; > + } > + DEBUG ((DEBUG_WARN, "%a: incomplete packet received\n", __FUNCTION__)); > + return EFI_DEVICE_ERROR; > + } > + > + gBS->CopyMem (Value, Res.Result, MIN (ValueLength, > ATSHA204A_OUTPUT_SIZE)); > + if (ValueLength < ATSHA204A_OUTPUT_SIZE) { > + break; > + } > + > + Value += ATSHA204A_OUTPUT_SIZE; > + ValueLength -= ATSHA204A_OUTPUT_SIZE; > + Retries = 0; > + } > + return EFI_SUCCESS; > +} > + > +EFI_STATUS > +AtSha204aInit ( > + IN EFI_HANDLE DriverBindingHandle, > + IN EFI_HANDLE ControllerHandle > + ) > +{ > + EFI_STATUS Status; > + ATSHA204A_DEV *AtSha204a; > + > + Status = gBS->AllocatePool (EfiBootServicesData, sizeof (ATSHA204A_DEV), > + (VOID **) &AtSha204a); > + if (EFI_ERROR (Status)) { > + return EFI_OUT_OF_RESOURCES; > + } > + > + AtSha204a->Signature = ATSHA204A_DEV_SIGNATURE; > + AtSha204a->Rng.GetInfo = AtSha240aGetInfo; > + AtSha204a->Rng.GetRNG = AtSha240aGetRNG; > + > + // > + // Open I2C I/O Protocol > + // > + Status = gBS->OpenProtocol (ControllerHandle, > + &gEfiI2cIoProtocolGuid, > + (VOID **)&AtSha204a->I2cIo, > + DriverBindingHandle, > + ControllerHandle, > + EFI_OPEN_PROTOCOL_BY_DRIVER); > + if (EFI_ERROR (Status)) { > + goto ErrorFreeDev; > + } > + > + Status = gBS->InstallProtocolInterface (&ControllerHandle, > + &gEfiRngProtocolGuid, > + EFI_NATIVE_INTERFACE, > + &AtSha204a->Rng); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, > + "Failed to install RNG protocol interface (Status == %r)\n", > + Status)); > + goto ErrorCloseProtocol; > + } > + > + return EFI_SUCCESS; > + > +ErrorCloseProtocol: > + gBS->CloseProtocol (ControllerHandle, &gEfiI2cIoProtocolGuid, > + DriverBindingHandle, ControllerHandle); > + > +ErrorFreeDev: > + gBS->FreePool (AtSha204a); > + > + return Status; > +} > + > +EFI_STATUS > +AtSha204aRelease ( > + IN EFI_HANDLE DriverBindingHandle, > + IN EFI_HANDLE ControllerHandle > + ) > +{ > + EFI_RNG_PROTOCOL *Rng; > + ATSHA204A_DEV *AtSha204a; > + EFI_STATUS Status; > + > + Status = gBS->HandleProtocol (ControllerHandle, > + &gEfiRngProtocolGuid, > + (VOID **)&Rng); > + ASSERT_EFI_ERROR (Status); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + AtSha204a = ATSHA204A_DEV_FROM_THIS (Rng); > + > + Status = gBS->UninstallProtocolInterface (ControllerHandle, > + &gEfiRngProtocolGuid, > + Rng); > + ASSERT_EFI_ERROR (Status); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + Status = gBS->CloseProtocol (ControllerHandle, > + &gEfiI2cIoProtocolGuid, > + DriverBindingHandle, > + ControllerHandle); > + ASSERT_EFI_ERROR (Status); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + gBS->FreePool (AtSha204a); > + > + return EFI_SUCCESS; > +} > diff --git a/Silicon/Atmel/AtSha204a/AtSha204aDriver.h > b/Silicon/Atmel/AtSha204a/AtSha204aDriver.h > new file mode 100644 > index 000000000000..315a450d34f2 > --- /dev/null > +++ b/Silicon/Atmel/AtSha204a/AtSha204aDriver.h > @@ -0,0 +1,81 @@ > +/** @file > + Device driver for the Atmel ATSHA204A random number generator. > + > + Copyright (c) 2018, Linaro Ltd. All rights reserved.<BR> > + > + This program and the accompanying materials > + are licensed and made available under the terms and conditions of the BSD > + License which accompanies this distribution. The full text of the license > may > + be found at http://opensource.org/licenses/bsd-license.php. > + > + 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 _ATSHA204A_I2C_HWRNG_DRIVER_H_ > +#define _ATSHA204A_I2C_HWRNG_DRIVER_H_ > + > +#include <Uefi.h> > +#include <Library/BaseMemoryLib.h> > +#include <Library/DebugLib.h> > +#include <Library/UefiBootServicesTableLib.h> > +#include <Library/UefiLib.h> > + > +#include <Protocol/Rng.h> > +#include <Protocol/I2cIo.h> > + > +#define ATSHA204A_OUTPUT_SIZE 32 > + > +#define ATSHA204A_DEV_SIGNATURE SIGNATURE_32('a','t','s','h') > + > +typedef struct { > + UINT32 Signature; > + EFI_I2C_IO_PROTOCOL *I2cIo; > + EFI_RNG_PROTOCOL Rng; > +} ATSHA204A_DEV; > + > +#define ATSHA204A_DEV_FROM_THIS(a) \ > + CR(a, ATSHA204A_DEV, Rng, ATSHA204A_DEV_SIGNATURE) > + > +#pragma pack(1) > +typedef struct { > + UINT8 Command; > + UINT8 Count; > + UINT8 Opcode; > + UINT8 Param1; > + UINT16 Param2; > + UINT16 Crc; > +} ATSHA204A_I2C_RNG_COMMAND; > + > +typedef struct { > + UINT8 Count; > + UINT8 Result[ATSHA204A_OUTPUT_SIZE]; > + UINT16 Crc; > +} ATSHA204A_I2C_RNG_RESULT; > +#pragma pack() > + > +typedef struct { > + UINTN OperationCount; > + EFI_I2C_OPERATION Operation; > +} I2C_RNG_REQUEST; > + > +#define ATSHA204A_COMMAND 0x3 > + > +#define ATSHA204A_OPCODE_RANDOM 0x1b > + > +extern EFI_COMPONENT_NAME2_PROTOCOL gAtSha204aDriverComponentName2; > + > +EFI_STATUS > +AtSha204aInit ( > + IN EFI_HANDLE DriverBindingHandle, > + IN EFI_HANDLE ControllerHandle > + ); > + > +EFI_STATUS > +AtSha204aRelease ( > + IN EFI_HANDLE DriverBindingHandle, > + IN EFI_HANDLE ControllerHandle > + ); > + > +#endif // _ATSHA204A_I2C_HWRNG_DRIVER_H_ > diff --git a/Silicon/Atmel/AtSha204a/AtSha204aDxe.inf > b/Silicon/Atmel/AtSha204a/AtSha204aDxe.inf > new file mode 100644 > index 000000000000..fe90cc538114 > --- /dev/null > +++ b/Silicon/Atmel/AtSha204a/AtSha204aDxe.inf > @@ -0,0 +1,52 @@ > +## @file > +# Device driver for the Atmel ATSHA204A random number generator. > +# > +# Copyright (c) 2018, Linaro Ltd. All rights reserved.<BR> > +# > +# This program and the accompanying materials > +# are licensed and made available under the terms and conditions of the BSD > +# License which accompanies this distribution. The full text of the license > may > +# be found at http://opensource.org/licenses/bsd-license.php. > +# > +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, > +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR > IMPLIED. > +# > +## > + > +[Defines] > + INF_VERSION = 0x0001001A > + BASE_NAME = AtSha204aDxe > + FILE_GUID = 8b8f683b-f376-4ba0-b8d7-b4bbd30319cc > + MODULE_TYPE = UEFI_DRIVER > + VERSION_STRING = 1.0 > + ENTRY_POINT = EntryPoint > + UNLOAD_IMAGE = UnloadImage > + > +# > +# VALID_ARCHITECTURES = AARCH64 ARM EBC IA32 IPF X64 > +# > + > +[Sources] > + AtSha204aDriver.c > + AtSha204aDriver.h > + ComponentName.c > + DriverBinding.c > + > +[Packages] > + MdePkg/MdePkg.dec > + Silicon/Atmel/AtSha204a/AtSha204a.dec > + > +[LibraryClasses] > + BaseMemoryLib > + DebugLib > + UefiBootServicesTableLib > + UefiDriverEntryPoint > + UefiLib > + > +[Protocols] > + gEfiRngProtocolGuid # PROTOCOL BY_START > + gEfiI2cIoProtocolGuid # PROTOCOL TO_START > + > +[Guids] > + gAtSha204aI2cDeviceGuid > + gEfiRngAlgorithmRaw > diff --git a/Silicon/Atmel/AtSha204a/ComponentName.c > b/Silicon/Atmel/AtSha204a/ComponentName.c > new file mode 100644 > index 000000000000..9893e7c4c2bf > --- /dev/null > +++ b/Silicon/Atmel/AtSha204a/ComponentName.c > @@ -0,0 +1,186 @@ > +/** @file > + UEFI Component Name(2) protocol implementation for AtSha204a driver. > + > + Copyright (c) 2018, Linaro Ltd. All rights reserved. > + > + This program and the accompanying materials > + are licensed and made available under the terms and conditions of the BSD > License > + which accompanies this distribution. The full text of the license may be > found at > + http://opensource.org/licenses/bsd-license.php > + > + 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 "AtSha204aDriver.h" > + > +STATIC EFI_UNICODE_STRING_TABLE mAtSha204aDriverNameTable[] = { > + { > + "en", > + (CHAR16 *)L"AtSha204a RNG I2C driver" > + }, > + { } > +}; > + > +STATIC EFI_UNICODE_STRING_TABLE mAtSha204aControllerNameTable[] = { > + { > + "en", > + (CHAR16 *)L"AtSha204a Random Number Generator (I2C)" > + }, > + { } > +}; > + > +/** > + Retrieves a Unicode string that is the user readable name of the driver. > + > + This function retrieves the user readable name of a driver in the form of a > + Unicode string. If the driver specified by This has a user readable name in > + the language specified by Language, then a pointer to the driver name is > + returned in DriverName, and EFI_SUCCESS is returned. If the driver > specified > + by This does not support the language specified by Language, > + then EFI_UNSUPPORTED is returned. > + > + @param This[in] A pointer to the > EFI_COMPONENT_NAME2_PROTOCOL or > + EFI_COMPONENT_NAME_PROTOCOL instance. > + > + @param Language[in] A pointer to a Null-terminated ASCII string > + array indicating the language. This is the > + language of the driver name 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. Language is specified > + in RFC 4646 or ISO 639-2 language code > format. > + > + @param DriverName[out] 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. > + > +**/ > +STATIC > +EFI_STATUS > +EFIAPI > +AtSha204aGetDriverName ( > + IN EFI_COMPONENT_NAME2_PROTOCOL *This, > + IN CHAR8 *Language, > + OUT CHAR16 **DriverName > + ) > +{ > + return LookupUnicodeString2 (Language, > + This->SupportedLanguages, > + mAtSha204aDriverNameTable, > + DriverName, > + FALSE); > +} > + > +/** > + Retrieves a Unicode string that is the user readable name of the controller > + that is being managed by a driver. > + > + This function retrieves the user readable name of the controller specified > by > + ControllerHandle and ChildHandle in the form of a Unicode string. If the > + driver specified by This has a user readable name in the language > specified by > + Language, then a pointer to the controller name is returned in > ControllerName, > + and EFI_SUCCESS is returned. If the driver specified by This is not > currently > + managing the controller specified by ControllerHandle and ChildHandle, > + then EFI_UNSUPPORTED is returned. If the driver specified by This does not > + support the language specified by Language, then EFI_UNSUPPORTED is > returned. > + > + @param This[in] A pointer to the > EFI_COMPONENT_NAME2_PROTOCOL or > + EFI_COMPONENT_NAME_PROTOCOL instance. > + > + @param ControllerHandle[in] 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[in] 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[in] A pointer to a Null-terminated ASCII string > + array indicating the language. This is the > + language of the driver name 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. Language is specified > in > + RFC 4646 or ISO 639-2 language code format. > + > + @param ControllerName[out] 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 NULL. > + > + @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. > + > +**/ > +STATIC > +EFI_STATUS > +EFIAPI > +AtSha204aGetControllerName ( > + IN EFI_COMPONENT_NAME2_PROTOCOL *This, > + IN EFI_HANDLE ControllerHandle, > + IN EFI_HANDLE ChildHandle > OPTIONAL, > + IN CHAR8 *Language, > + OUT CHAR16 **ControllerName > + ) > +{ > + if (ChildHandle != NULL) { > + return EFI_UNSUPPORTED; > + } > + > + return LookupUnicodeString2 (Language, > + This->SupportedLanguages, > + mAtSha204aControllerNameTable, > + ControllerName, > + FALSE); > +} > + > +// > +// EFI Component Name 2 Protocol > +// > +EFI_COMPONENT_NAME2_PROTOCOL gAtSha204aDriverComponentName2 = { > + AtSha204aGetDriverName, > + AtSha204aGetControllerName, > + "en" > +}; > diff --git a/Silicon/Atmel/AtSha204a/DriverBinding.c > b/Silicon/Atmel/AtSha204a/DriverBinding.c > new file mode 100644 > index 000000000000..17e61f96e8c5 > --- /dev/null > +++ b/Silicon/Atmel/AtSha204a/DriverBinding.c > @@ -0,0 +1,242 @@ > +/** @file > + Device driver for the Atmel ATSHA204A random number generator. > + > + Copyright (c) 2018, Linaro Ltd. All rights reserved.<BR> > + > + This program and the accompanying materials > + are licensed and made available under the terms and conditions of the BSD > + License which accompanies this distribution. The full text of the license > may > + be found at http://opensource.org/licenses/bsd-license.php. > + > + 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 <Library/UefiDriverEntryPoint.h> > + > +#include "AtSha204aDriver.h" > + > +/** > + Tests to see if this driver supports a given controller. > + > + @param This[in] A pointer to the > EFI_DRIVER_BINDING_PROTOCOL > + instance. > + @param ControllerHandle[in] The handle of the controller to test. > + @param RemainingDevicePath[in] The remaining device path. > + (Ignored - this is not a bus driver.) > + > + @retval EFI_SUCCESS The driver supports this controller. > + @retval EFI_ALREADY_STARTED The device specified by ControllerHandle > is > + already being managed by the driver > specified > + by This. > + @retval EFI_UNSUPPORTED The device specified by ControllerHandle > is > + not supported by the driver specified by > This. > + > +**/ > +EFI_STATUS > +EFIAPI > +I2cHwrngDriverBindingSupported ( > + IN EFI_DRIVER_BINDING_PROTOCOL *This, > + IN EFI_HANDLE ControllerHandle, > + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath > + ) > +{ > + EFI_I2C_IO_PROTOCOL *I2cIo; > + EFI_STATUS Status; > + > + // > + // Connect to the I2C stack > + // > + Status = gBS->OpenProtocol (ControllerHandle, > + &gEfiI2cIoProtocolGuid, > + (VOID **) &I2cIo, > + This->DriverBindingHandle, > + ControllerHandle, > + EFI_OPEN_PROTOCOL_BY_DRIVER); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + if (CompareGuid (I2cIo->DeviceGuid, &gAtSha204aI2cDeviceGuid)) { > + DEBUG ((DEBUG_INIT | DEBUG_INFO, "Detected AtSha204a RNG device\n")); > + Status = EFI_SUCCESS; > + } else { > + Status = EFI_UNSUPPORTED; > + } > + > + // > + // Clean up. > + // > + gBS->CloseProtocol (ControllerHandle, > + &gEfiI2cIoProtocolGuid, > + This->DriverBindingHandle, > + ControllerHandle); > + > + return Status; > +} > + > + > +/** > + Starts a device controller or a bus controller. > + > + @param[in] This A pointer to the > EFI_DRIVER_BINDING_PROTOCOL > + instance. > + @param[in] ControllerHandle The handle of the device to start. This > + handle must support a protocol interface > that > + supplies an I/O abstraction to the driver. > + @param[in] RemainingDevicePath The remaining portion of the device path. > + (Ignored - this is not a bus driver.) > + > + @retval EFI_SUCCESS The device was started. > + @retval EFI_DEVICE_ERROR The device could not be started due to a > + device error. > + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to > a > + lack of resources. > + > +**/ > +EFI_STATUS > +EFIAPI > +I2cHwrngDriverBindingStart ( > + IN EFI_DRIVER_BINDING_PROTOCOL *This, > + IN EFI_HANDLE ControllerHandle, > + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL > + ) > +{ > + return AtSha204aInit (This->DriverBindingHandle, ControllerHandle); > +} > + > + > +/** > + Stops a device controller or a bus controller. > + > + @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL > + instance. > + @param[in] ControllerHandle A handle to the device being stopped. The > handle > + must support a bus specific I/O protocol for > the > + driver to use to stop the device. > + @param[in] NumberOfChildren The number of child device handles in > + ChildHandleBuffer. > + @param[in] ChildHandleBuffer An array of child handles to be freed. May be > + NULL if NumberOfChildren is 0. > + > + @retval EFI_SUCCESS The device was stopped. > + @retval EFI_DEVICE_ERROR The device could not be stopped due to a > device > + error. > + > +**/ > +EFI_STATUS > +EFIAPI > +I2cHwrngDriverBindingStop ( > + IN EFI_DRIVER_BINDING_PROTOCOL *This, > + IN EFI_HANDLE ControllerHandle, > + IN UINTN NumberOfChildren, > + IN EFI_HANDLE *ChildHandleBuffer OPTIONAL > + ) > +{ > + return AtSha204aRelease (This->DriverBindingHandle, ControllerHandle); > +} > + > + > +STATIC > +EFI_DRIVER_BINDING_PROTOCOL gI2cHwrngDriverBinding = { > + I2cHwrngDriverBindingSupported, > + I2cHwrngDriverBindingStart, > + I2cHwrngDriverBindingStop, > + 0xa, > + NULL, > + NULL > +}; > + > + > +/** > + The entry point of AtSha204a UEFI Driver. > + > + @param ImageHandle The image handle of the UEFI Driver. > + @param SystemTable A pointer to the EFI System Table. > + > + @retval EFI_SUCCESS The Driver or UEFI Driver exited > normally. > + @retval EFI_INCOMPATIBLE_VERSION _gUefiDriverRevision is greater than > + SystemTable->Hdr.Revision. > + > +**/ > +EFI_STATUS > +EFIAPI > +EntryPoint ( > + IN EFI_HANDLE ImageHandle, > + IN EFI_SYSTEM_TABLE *SystemTable > + ) > +{ > + EFI_STATUS Status; > + > + // > + // Add the driver to the list of drivers > + // > + Status = EfiLibInstallDriverBindingComponentName2 ( > + ImageHandle, SystemTable, &gI2cHwrngDriverBinding, ImageHandle, > + NULL, &gAtSha204aDriverComponentName2); > + ASSERT_EFI_ERROR (Status); > + > + DEBUG ((DEBUG_INIT | DEBUG_INFO, "*** Installed AtSha204a driver! ***\n")); > + > + return EFI_SUCCESS; > +} > + > + > +/** > + Unload function for the AtSha204a Driver. > + > + @param ImageHandle[in] The allocated handle for the EFI image > + > + @retval EFI_SUCCESS The driver was unloaded successfully > + @retval EFI_INVALID_PARAMETER ImageHandle is not a valid image handle. > + > +**/ > +EFI_STATUS > +EFIAPI > +UnloadImage ( > + IN EFI_HANDLE ImageHandle > + ) > +{ > + EFI_STATUS Status; > + EFI_HANDLE *HandleBuffer; > + UINTN HandleCount; > + UINTN Index; > + > + // > + // Retrieve all I2C I/O handles in the handle database > + // > + Status = gBS->LocateHandleBuffer (ByProtocol, > + &gEfiI2cIoProtocolGuid, > + NULL, > + &HandleCount, > + &HandleBuffer); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + // > + // Disconnect the driver from the handles in the handle database > + // > + for (Index = 0; Index < HandleCount; Index++) { > + Status = gBS->DisconnectController (HandleBuffer[Index], > + gImageHandle, > + NULL); > + } > + > + // > + // Free the handle array > + // > + gBS->FreePool (HandleBuffer); > + > + // > + // Uninstall protocols installed by the driver in its entrypoint > + // > + Status = gBS->UninstallMultipleProtocolInterfaces (ImageHandle, > + &gEfiDriverBindingProtocolGuid, > + &gI2cHwrngDriverBinding, > + NULL > + ); > + > + return EFI_SUCCESS; > +} > -- > 2.11.0 > _______________________________________________ edk2-devel mailing list [email protected] https://lists.01.org/mailman/listinfo/edk2-devel

