On 02/23/18 12:48, Udit Kumar wrote:
> Hi Laszlo/Leif,
> 
> For short term, is this ok to keep this lib under Silicon/NXP, here we are 
> assuming  
> CPU will always on be LE mode whereas IP can vary between LE/BE mode ?
> 
> For long term, we can discuss on APIs/name of Lib/Function name etc
> We will update our code, as per agreement.

I think this is not my call; please talk to Leif and Ard.

Thanks
Laszlo

> For me, Suggested approach is ok as well to keep CPU endianness in ARM 
> package.
> but need views from Ard/Leif here.
> 
> Thanks
> Udit
> 
>> -----Original Message-----
>> From: Laszlo Ersek [mailto:ler...@redhat.com]
>> Sent: Friday, February 23, 2018 4:17 PM
>> To: Udit Kumar <udit.ku...@nxp.com>; Leif Lindholm
>> <leif.lindh...@linaro.org>
>> Cc: michael.d.kin...@intel.com; edk2-devel@lists.01.org;
>> ard.biesheu...@linaro.org
>> Subject: Re: [edk2] [PATCH edk2-platforms 01/39] Silicon/NXP: Add support
>> for Big Endian Mmio APIs
>>
>> On 02/23/18 11:25, Udit Kumar wrote:
>>>
>>>
>>>> -----Original Message-----
>>>> From: edk2-devel [mailto:edk2-devel-boun...@lists.01.org] On Behalf
>>>> Of Laszlo Ersek
>>>> Sent: Thursday, February 22, 2018 7:26 PM
>>>> To: Leif Lindholm <leif.lindh...@linaro.org>
>>>> Cc: michael.d.kin...@intel.com; edk2-devel@lists.01.org;
>>>> ard.biesheu...@linaro.org
>>>> Subject: Re: [edk2] [PATCH edk2-platforms 01/39] Silicon/NXP: Add
>>>> support for Big Endian Mmio APIs
>>>>
>>>> On 02/22/18 12:52, Leif Lindholm wrote:
>>>>> On Thu, Feb 22, 2018 at 09:34:05AM +0100, Laszlo Ersek wrote:
>>>>
>>>>>>> But that brings back the complication as to how we have a driver
>>>>>>> that needs an LE IO library to write output, and a BE IO library
>>>>>>> to manipulate the hardware.
>>>>>>
>>>>>> Can you please explain the "write output" use case more precisely?
>>>>>>
>>>>>> My thinking would be this:
>>>>>>
>>>>>> - Use the IoLib class directly for "writing output" in little
>>>>>> endian byte order (which is still unclear to me sorry).
>>>>>
>>>>> If the IoLib class is mapped to a an instance that byte-swaps
>>>>> (hereto referred to as BeIoLib if IoLibSwap is unsuitable), would we
>>>>> not then end up mapping the non-swapping, currently implemented in
>>>>> BaseLibIoIntrinsic, variant as BeIoLib? Or if not, do we end up
>>>>> needing to duplicated all IoLib implementation .infs to provide an
>>>>> IoLib and a BeIoLib for each?
>>>>>
>>>>> It's at that point I burst an aneurysm.
>>>>> Am I overthinking/underthinking this?
>>>>
>>>> We need two library classes, one for talking to LE devices and
>>>> another to BE devices. These should be usable in a given module at
>>>> the same time, as Ard says.
>>>>
>>>> Both library classes need to work on both LE and BE CPUs (working
>>>> from your suggestion that UEFI might grow BE CPU support at some
>>>> point). Whether that is implemented by dumb, separate library
>>>> instances (yielding in total 2*2=4 library instances), or by smart,
>>>> CPU-endianness-agnostic library instances (in total, 2), is a
>>>> different question.
>>>>
>>>> Note that such "smarts" could be less than trivial to implement:
>>>> - check CPU endianness in each library API?
>>>> - or check in the lib constructor only, and flip some function
>>>>   pointers?
>>>> - use a dynamic PCD for caching CPU endianness?
>>>> - use a HOB for the same?
>>>> - use a lib global variable (for caching only on the module level)?
>>>>
>>>> I think the solution that saves the most on the *source* code size
>>>> is:
>>>> - introduce the BeIoLib class
>>>> - duplicate the MMIO functions from BaseIoLibIntrinsic to the one
>>>>   BeIoLib instance that we introduce
>>>> - modify the MMIO functions in *both* lib instances (original LE, and
>>>>   new BE), like this:
>>>>
>>>>   - If the CPU architecture is known to be bound to a single
>>>>     endianness, then hardcode the appropriate operation. This can be
>>>>     done with preprocessor macros, or with the architecture support
>>>>     of INF files / separate source files. For example, on IA32 and
>>>>     X64, the IoLib instance should work transparently,
>>>>     unconditionally, and the BeIoLib instance should byte-swap,
>>>>     unconditionally.
>>>>
>>>>   - On other CPU arches, all the wider-than-byte MMIO functions, in
>>>>     *both* lib instances should do something like this:
>>>>
>>>>     //
>>>>     // at file scope
>>>>     //
>>>>     STATIC CONST UINT16 mOne = 1;
>>>>
>>>>     //
>>>>     // at function scope
>>>>     //
>>>>     if (*(CONST UINT8 *)&mOne == 1) {
>>>>       //
>>>>       // CPU in LE mode:
>>>>       // - work transparently in the IoLib instance
>>>>       // - byte-swap in the BeIoLib instance
>>>>       //
>>>>     } else {
>>>>       //
>>>>       // CPU in BE mode:
>>>>       // - byte-swap in the IoLib instance
>>>>       // - work transparently in the BeIoLib instance
>>>>       //
>>>>     }
>>>
>>> You meant, sort of cpu_to_le and cpu_to_be sort of APIs
>>
>> I'm lost. I don't know how to put it any clearer. Let me try with actual
>> code.
>>
>> (a) Suggested for "MdePkg/Library/BaseIoLibIntrinsic/IoLib.c", which is
>> used on IA32 and X64, therefore CPU byte order is little endian only:
>>
>>> UINT32
>>> EFIAPI
>>> MmioWrite32 (
>>>   IN      UINTN                     Address,
>>>   IN      UINT32                    Value
>>>   )
>>> {
>>>   ASSERT ((Address & 3) == 0);
>>>
>>>   MemoryFence ();
>>>   *(volatile UINT32*)Address = Value;
>>>   MemoryFence ();
>>>
>>>   return Value;
>>> }
>>
>> In other words, no change to the current implementation.
>>
>>
>> (b) Suggested for "MdePkg/Library/BaseBeIoLibIntrinsic/IoLib.c", also to
>> be used on IA32 and X64. Because the CPU byte order is LE only, this
>> variant will byte-swap unconditionally.
>>
>>> UINT32
>>> EFIAPI
>>> BeMmioWrite32 (
>>>   IN      UINTN                     Address,
>>>   IN      UINT32                    Value
>>>   )
>>> {
>>>   ASSERT ((Address & 3) == 0);
>>>
>>>   MemoryFence ();
>>>   *(volatile UINT32*)Address = SwapBytes32 (Value);
>>>   MemoryFence ();
>>>
>>>   return Value;
>>> }
>>
>> (c) Suggested for "MdePkg/Library/BaseIoLibIntrinsic/IoLibArm.c", which
>> is used on ARM and AARCH64. And here I'll assume that the CPU byte order
>> on those can be either LE or BE.
>>
>>> UINT32
>>> EFIAPI
>>> MmioWrite32 (
>>>   IN      UINTN                     Address,
>>>   IN      UINT32                    Value
>>>   )
>>> {
>>>   ASSERT ((Address & 3) == 0);
>>>   *(volatile UINT32*)Address = (*(CONST UINT8 *)&mOne == 1) ?
>>>                                Value :
>>>                                SwapBytes32 (Value);
>>>   return Value;
>>> }
>>
>>
>> (d) Suggested for "MdePkg/Library/BaseBeIoLibIntrinsic/BeIoLibArm.c",
>> which is to be used on ARM and AARCH64. And here I'll assume that the
>> CPU byte order on those can be either LE or BE.
>>
>>> UINT32
>>> EFIAPI
>>> BeMmioWrite32 (
>>>   IN      UINTN                     Address,
>>>   IN      UINT32                    Value
>>>   )
>>> {
>>>   ASSERT ((Address & 3) == 0);
>>>   *(volatile UINT32*)Address = (*(CONST UINT8 *)&mOne == 1) ?
>>>                                SwapBytes32 (Value) :
>>>                                Value;
>>>   return Value;
>>> }
> 
> 
>> Laszlo

_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel

Reply via email to