> On Nov 14, 2015, at 9:24 AM, Michael Zimmermann <[email protected]> 
> wrote:
> 
>> There is most likely a raise to TPL_HIGH and a TPL restore in that path
> that causes event dispatch.
> 
> Is that bad?
> 

Oops did not reply.....

No that is OK. 

>> Is it one of the edk2 timer libs? If so which one?
> 
> Nope it's my own, platform specific one(my device hasn't been merged to the
> official sources yet).
> 

Most of the other TimerLib implementations use a free running counter. 

Thanks,

Andrew Fish

> Michael
> 
> 
> On Sat, Nov 14, 2015 at 6:11 PM, Andrew Fish <[email protected]> wrote:
> 
>> 
>>> On Nov 13, 2015, at 10:53 PM, Michael Zimmermann <
>> [email protected]> wrote:
>>> 
>>> 
>>> I think I've made some progress.
>>> Thx to the fact that the only thing stuck is the ARM thread mode and the
>>> timer interrupts are still fired(I verified that my callback is called
>> from
>>> an interrupt, being it a fluke or not) I could easily dump the current PC
>>> of the DxeCore context.
>>> 
>> 
>> There is most likely a raise to TPL_HIGH and a TPL restore in that path
>> that causes event dispatch.
>> 
>>> This way I discovered that the code is stuck in the delay functions of
>> the
>>> timerLib because they're not thread safe.
>>> 
>> 
>> Is it one of the edk2 timer libs? If so which one?
>> 
>> Thanks,
>> 
>> Andrew Fish
>> 
>>> The reason is that a hw counter gets reset and started for this and if
>> this
>>> happens from an interrupt(UART uses delay functions) while the thread
>> mode
>>> is whiting for the counter to reach an specific value it will just wait
>>> forever because the counter gets disabled after the delay.
>>> 
>>> Code:
>>> usecs = (usecs * 33 + 1000 - 33) / 1000;
>>> 
>>> writel(0, GPT_CLEAR);
>>> writel(0, GPT_ENABLE);
>>> while (readl(GPT_COUNT_VAL) != 0) ;
>>> 
>>> writel(GPT_ENABLE_EN, GPT_ENABLE);
>>> while (readl(GPT_COUNT_VAL) < usecs) ;
>>> 
>>> writel(0, GPT_ENABLE);
>>> writel(0, GPT_CLEAR);
>>> 
>>> I guess I need to try keeping the counter running and detect when it
>> rolled
>>> over to make it thread-safe.
>>> 
>>> Michael
>>> 
>>> On Fri, Nov 13, 2015 at 1:14 AM, Andrew Fish <[email protected]> wrote:
>>> 
>>>> 
>>>>> On Nov 12, 2015, at 11:21 AM, Michael Zimmermann <
>>>> [email protected]> wrote:
>>>>> 
>>>>> thx for this information.
>>>>> I don't have any debug hw but UART.
>>>>> 
>>>>> After some careful DEBUG printing and tracing the call stack using
>>>>> '__builtin_return_address(0)'
>>>> 
>>>> FYI the edk2 has a portable form of this RETURN_ADDRESS(0)
>>>> 
>>>>> I found that the application's dead happens
>>>>> at 'WaitForEvent'
>>>> 
>>>> The WaitForEvent() is what happens at the shell prompt when it is
>> waiting
>>>> for keyboard input. So that is functioning as intended.
>> gBS->WaitForEvent()
>>>> is the power efficient way to wait.
>>>> 
>>>> If you look at CoreWaitForEvent() it checks all the events, and then
>> calls
>>>> CoreSignalEvent with the gIdleLoopEvent. If the DXE Cpu driver supports
>>>> this feature gIdleLoopEvent will put the CPU in a low power state until
>> the
>>>> next timer tick. Since  CoreWaitForEvent() checked all the event state
>> it
>>>> can not change until the next timer tick so this lets the system spend
>> its
>>>> idle time in a lower power mode.
>>>> 
>>>> 
>>>> 
>> https://github.com/tianocore/edk2/blob/master/MdeModulePkg/Core/Dxe/Event/Event.c#L685
>>>> for(;;) {
>>>> 
>>>>   for(Index = 0; Index < NumberOfEvents; Index++) {
>>>> 
>>>>     Status = CoreCheckEvent (UserEvents[Index]);
>>>> 
>>>>     //
>>>>     // provide index of event that caused problem
>>>>     //
>>>>     if (Status != EFI_NOT_READY) {
>>>>       if (UserIndex != NULL) {
>>>>         *UserIndex = Index;
>>>>       }
>>>>       return Status;
>>>>     }
>>>>   }
>>>> 
>>>>   //
>>>>   // Signal the Idle event
>>>>   //
>>>>   CoreSignalEvent (gIdleLoopEvent);
>>>> }
>>>> 
>>>> So if you are really stuck here it could imply your Simple Text In is
>>>> hung? Maybe your issue is data corruption vs an event issue?
>>>> 
>>>>> and that there aren't any long running events(it returns
>>>>> from CoreDispatchEventNotifies and CoreRestoreTpl everytime).
>>>>> 
>>>>> I'm not sure this is always the case though because without the DEBUG's
>>>> the
>>>>> application can even stop when the edk2 shell is printing the device
>> map
>>>>> and WaitForEvent usually is only used for key input.
>>>>> 
>>>>> isn't there some GCC option to save the stacktrace so I can dump it
>> after
>>>>> some seconds runtime(when the system died) and just print the whole
>>>>> backtrace?(like the linux kernel does).
>>>>> 
>>>> 
>>>> Well this is when it gets tricky. For VC++ you can only
>> _ReturnAddress(),
>>>> and that is equivalent of __builtin_return_address(0) on the GCC side.
>> But
>>>> it gets worse... To get a stack trace for X64 with VC++ you need
>> symbols as
>>>> the unwind is in the .PDB file.
>>>> 
>>>> For clang, and I think with the right GCC compiler flags, you can walk
>> the
>>>> stack as each routine saves the frame pointer on entry. This is a simple
>>>> X64 C function that just returns 0. The push of the %rbp and saving %rsp
>>>> allow the stack to be unwound in software.
>>>> 
>>>>       pushq   %rbp
>>>>       movq    %rsp, %rbp
>>>>       xorl            %eax, %eax
>>>>       popq    %rbp
>>>>       retq
>>>> 
>>>> So it is possible to unwind the stack in software.
>>>> 
>>>> Simple answer is try RETURN_ADDRESS(1), RETURN_ADDRESS(2), etc. If it is
>>>> supported the compiler will generate the code to unwind for you.
>>>> 
>>>> Complex answer is write the stack unwind code, if it is possible? Which
>>>> Processor and I assume you are using GCC?
>>>> 
>>>> You can use the GetImageName() function in
>>>> 
>> https://github.com/tianocore/edk2/blob/master/ArmPkg/Library/DefaultExceptionHandlerLib/DefaultExceptionHandlerUefi.c#L64
>>>> to see how you can use the PE/COFF library functions to convert a
>>>> FaultAddress to the ImageBase, and name of the image. If you know the
>>>> offset into the image relative to the start you can load image in gdb
>> from
>>>> the build output directory and see what code it maps to.
>>>> 
>>>> The X86 version of all this lives:
>>>> 
>> https://github.com/tianocore/edk2/blob/master/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c
>>>> 
>>>> Thanks,
>>>> 
>>>> Andrew Fish
>>>> 
>>>>> On Thu, Nov 12, 2015 at 7:39 PM, Andrew Fish <[email protected]> wrote:
>>>>> 
>>>>>> 
>>>>>> On Nov 12, 2015, at 9:05 AM, Michael Zimmermann <
>>>> [email protected]>
>>>>>> wrote:
>>>>>> 
>>>>>> thx, this perfectly explains my situation(that EDK2 shell stops while
>>>>>> printing sth. like the map or waiting for this 5s startup.nsh
>> timeout).
>>>>>> 
>>>>>> So this means that processing the event queue is caused by any API
>> call
>>>>>> which never returns to the DXE phase for some reason.
>>>>>> 
>>>>>> 
>>>>>> You should also check your code looking for TPL violations. Calling
>> EFI
>>>>>> Services at to high a TPL can lead to undefined behavior.
>>>>>> 
>>>>>> If you look at the UEFI 2.5 spec, Section 6.1 Event, Timer, and Task
>>>>>> Priority Services Table 23 lists TPL Restrictions. You can check that
>>>> your
>>>>>> code is not violating any of these restrictions. The natural reaction
>>>> for
>>>>>> some one having performance issues is to cheat and try to elevate
>> their
>>>>>> TPL.
>>>>>> 
>>>>>> 
>>>>>> ...
>>>>>> 
>>>>>> The class of bugs created by calling EFI Services at to hight a TPL
>> are
>>>>>> usually reentrancy related. Basically the locks in the DXE Core raise
>>>> TPL
>>>>>> to protect critical sections, like the protocol data base or event
>>>> queue.
>>>>>> Calling at an illegal TPL can cause corruption of some of these
>>>> structures,
>>>>>> and thus undefined behavior.
>>>>>> 
>>>>>> Another possibility is an event TPL deadlock. When your event runs at
>> a
>>>>>> TPL only events of a higher TPL can run. Your event is blocking code
>> at
>>>> <=
>>>>>> current TPL from running. So if your event is waiting on something to
>>>>>> complete that needs to run at <= the current TPL that code is starved
>>>> and
>>>>>> will never get run. The TPL Restriction table is the guide here also.
>>>> For
>>>>>> example if you driver implements Block IO it can be called at TPL <=
>>>>>> TPL_CALLBACK, so if your driver has an event that needs to complete to
>>>> make
>>>>>> forward progress it needs to run at TPL_NOTIFY.
>>>>>> 
>>>>>> Since you are producing GOP, there is going to be system code that
>>>>>> implements Simple Text Output on top of GOP so you inherit those TPL
>>>>>> restrictions.
>>>>>> 
>>>>>> Is there a special way to debug the event system or do I have to put
>>>> DEBUG
>>>>>> calls all over the place?
>>>>>> 
>>>>>> 
>>>>>> Actually putting DEBUG prints all over the place can make it worse as
>>>> you
>>>>>> can increase the amount of time spent processing events.
>>>>>> 
>>>>>> I'm not sure if you have a debugger, but if you do....
>>>>>> 1) I'd break in a few times during the hang to try and get an idea of
>>>>>> which event is taking all the time from the back trace
>>>>>> 2) Pay attention to the TPL when you break in, dump gEfiCurrentTpl
>>>>>> 3) You can walk the gEventQueue[] LIST_ENTRY to see what events are
>>>>>> active. >= your current TPL.
>>>>>> 4) As I mentioned I have lldb scripts to dump queues so you can figure
>>>> out
>>>>>> the high frequency timer functions and inspect that code.
>>>>>> 
>>>>>> If you don't have a debugger...
>>>>>> 1) Add DEBUG print to CoreCreateEventInternal() and print out info
>> about
>>>>>> timer events that get created. Then you can look at the timer event
>>>>>> functions.
>>>>>> 2) CoreDispatchEventNotifies() calls the event notify functions.
>>>>>> Event->NotifyFunction (Event, Event->NotifyContext);
>>>>>> You can use the TimerLib to try and figure out what event is taking al
>>>> the
>>>>>> time. You can DEBUG print the slowest function, and maybe only do it
>>>> every
>>>>>> Nth time so you don't do it 1,000 times a second.
>>>>>> You could also add code to figure out if the function is running
>> longer
>>>>>> than (or some large percentage of) its period.
>>>>>> 
>>>>>> 
>>>>>> Caveat Emptor ....
>>>>>> Assume it is your event and figure out if you are doing something slow
>>>> at
>>>>>> an elevated TPL,  calling a service at too hight a TPL., or have TPL
>>>>>> related deadlock based on the TPL restrictions.
>>>>>> 
>>>>>> Thanks,
>>>>>> 
>>>>>> Andrew Fish
>>>>>> 
>>>>>> PS Sorry if this is more detail than you needed, but I figured other
>>>> folks
>>>>>> might find this useful.
>>>>>> 
>>>>>> 
>>>>>> On Thu, Nov 12, 2015 at 5:44 PM, Andrew Fish <[email protected]> wrote:
>>>>>> 
>>>>>>> 
>>>>>>>> On Nov 12, 2015, at 3:28 AM, Andrew Fish <[email protected]> wrote:
>>>>>>>> 
>>>>>>>>> 
>>>>>>>>> On Nov 12, 2015, at 3:22 AM, Andrew Fish <[email protected]> wrote:
>>>>>>>>> 
>>>>>>>>> 
>>>>>>>>>> On Nov 12, 2015, at 12:49 AM, Michael Zimmermann <
>>>>>>> [email protected]> wrote:
>>>>>>>>>> 
>>>>>>>>>> Stall was just an example, I can also use DEBUG. My timer interval
>>>> is
>>>>>>>>>> 100ms(I converted it from the 100ns unit).
>>>>>>>>>> 
>>>>>>>>>> What I meant with "thread mode code" is the "normal" non IRQ
>> context
>>>>>>> code
>>>>>>>>>> running on the CPU. That means that there are actually two
>> contexts
>>>> in
>>>>>>>>>> EDK2, the exception(i.e. IRQ's like the Timer/Watchdog) and the
>>>>>>> normal mode
>>>>>>>>>> all code is running in.
>>>>>>>>>> 
>>>>>>>>> 
>>>>>>>>> OK thanks that helps. The timer ISR runs in interrupt context, and
>>>>>>> from an ARM point of view EFI is running the ARM "Thread mode".  The
>>>> ISR
>>>>>>> context is an implementation detail and not really defined by the
>>>>>>> specification.
>>>>>>>>> 
>>>>>>>>> I'd also point out the Events dispatch independent of the interrupt
>>>>>>> context. gBS->RestoreTpl() can cause events to dispatch. For example
>> a
>>>> lot
>>>>>>> of the EFI Protocol services have locks that raise TPL to prevent
>>>>>>> recursion. When these locks are released and the TPL is restored
>>>> events are
>>>>>>> dispatched. So just calling EFI services can cause events to run. So
>>>>>>> conceptually you can ignore the interrupt context, as that is used to
>>>>>>> implement the timer tick. Every thing else is an event that runs in
>> the
>>>>>>> main EFI context.
>>>>>>>>> 
>>>>>>>>> 
>>>>>>> 
>>>> 
>> https://github.com/tianocore/edk2/blob/master/MdeModulePkg/Core/Dxe/Event/Tpl.c#L126
>>>>>>>>> 
>>>>>>>> 
>>>>>>>> As Kinney pointed out the events are cooperative and there is no
>>>>>>> scheduler, so if you are getting stuck some chunk of code is running
>>>> too
>>>>>>> long at an elevated TPL. You may need to performance profile to
>> figure
>>>> out
>>>>>>> the bad code.
>>>>>>>> 
>>>>>>> 
>>>>>>> The events are managed by queues in the DXE Core. The events are
>>>>>>> described by the IEVENT data structure and linked into queues based
>> on
>>>>>>> state. The state transition to the event is calling a C function
>>>> stored in
>>>>>>> the IEVENT. The event must return, or call an EFI service, to give
>>>> control
>>>>>>> back to the DXE Core.
>>>>>>> 
>>>>>>> 
>>>>>>> 
>>>> 
>> https://github.com/tianocore/edk2/blob/master/MdeModulePkg/Core/Dxe/Event/Event.c
>>>>>>> 
>>>>>>> ///
>>>>>>> /// gEventQueueLock - Protects the event queues
>>>>>>> ///
>>>>>>> EFI_LOCK gEventQueueLock = EFI_INITIALIZE_LOCK_VARIABLE
>>>> (TPL_HIGH_LEVEL);
>>>>>>> 
>>>>>>> ///
>>>>>>> /// gEventQueue - A list of event's to notify for each priority level
>>>>>>> ///
>>>>>>> LIST_ENTRY      gEventQueue[TPL_HIGH_LEVEL + 1];
>>>>>>> 
>>>>>>> ///
>>>>>>> /// gEventPending - A bitmask of the EventQueues that are pending
>>>>>>> ///
>>>>>>> UINTN           gEventPending = 0;
>>>>>>> 
>>>>>>> ///
>>>>>>> /// gEventSignalQueue - A list of events to signal based on
>> EventGroup
>>>>>>> type
>>>>>>> ///
>>>>>>> LIST_ENTRY      gEventSignalQueue = INITIALIZE_LIST_HEAD_VARIABLE
>>>>>>> (gEventSignalQueue);
>>>>>>> 
>>>>>>> It is possible to write a debugger script to dump out the info about
>>>> the
>>>>>>> events if you have source level debug available for the DXE Core.
>>>>>>> 
>>>>>>> Thanks,
>>>>>>> 
>>>>>>> Andrew Fish
>>>>>>> 
>>>>>>>> Thanks,
>>>>>>>> 
>>>>>>>> Andrew Fish
>>>>>>>> 
>>>>>>>> 
>>>>>>>>> Thanks,
>>>>>>>>> 
>>>>>>>>> Andrew Fish
>>>>>>>>> 
>>>>>>>>> 
>>>>>>>>>> On Thu, Nov 12, 2015 at 9:27 AM, Andrew Fish <[email protected]>
>>>> wrote:
>>>>>>>>>> 
>>>>>>>>>>> 
>>>>>>>>>>>> On Nov 11, 2015, at 11:51 PM, Michael Zimmermann <
>>>>>>>>>>> [email protected]> wrote:
>>>>>>>>>>>> 
>>>>>>>>>>>> I've started investigating in the timer event problem and I
>> think
>>>> I
>>>>>>> have
>>>>>>>>>>>> some weird problem with my platform drivers(I hope, so it's not
>> a
>>>>>>> EDK2
>>>>>>>>>>> bug).
>>>>>>>>>>>> 
>>>>>>>>>>>> If I create a timer that runs every 100ms which does nothing
>> but a
>>>>>>>>>>>> stall(1), the thread mode code stops after some random
>>>> time(usually
>>>>>>> in
>>>>>>>>>>> edk2
>>>>>>>>>>>> shell so I guess it's a race condition which needs some cpu
>> load).
>>>>>>>>>>>> 
>>>>>>>>>>> 
>>>>>>>>>>> Michael,
>>>>>>>>>>> 
>>>>>>>>>>> Watch out as Stall() is Microseconds, and SetTimer() is 100ns
>> I've
>>>>>>> seen
>>>>>>>>>>> bugs like that before in code.
>>>>>>>>>>> 
>>>>>>>>>>>> When threadmode code is stopped the timer continues getting
>> called
>>>>>>> and
>>>>>>>>>>> even
>>>>>>>>>>>> if I stop the timer afterwards(with CloseEvent) it keeps being
>>>>>>> stopped.
>>>>>>>>>>>> 
>>>>>>>>>>>> Is there a way to get the threadmode context from inside a timer
>>>>>>>>>>> callback?
>>>>>>>>>>>> This way I could read the PC to check what's going on.
>>>>>>>>>>>> 
>>>>>>>>>>> 
>>>>>>>>>>> There are no threads. EFI is an event model. If your code is
>>>> running
>>>>>>> you
>>>>>>>>>>> are blocking every one else's forward progress. Only code running
>>>> at
>>>>>>> a
>>>>>>>>>>> higher TPL can preempt. So when your event is running it is
>>>> blocking
>>>>>>> the
>>>>>>>>>>> main flow and any event trying to run at <= TPL of your event
>> from
>>>>>>> making
>>>>>>>>>>> forward progress. gBS->Stall() does not yield, it is no different
>>>>>>> than
>>>>>>>>>>> running code.
>>>>>>>>>>> 
>>>>>>>>>>> So there is only one context, you can print it out any time you
>>>> want.
>>>>>>>>>>> 
>>>>>>>>>>> Thanks,
>>>>>>>>>>> 
>>>>>>>>>>> Andrew Fish
>>>>>>>>>>> 
>>>>>>>>>>> PS When folks yell at us for not having threads in EFI we point
>>>> them
>>>>>>> at:
>>>>>>>>>>> 
>> https://urldefense.proofpoint.com/v2/url?u=https-3A__web.stanford.edu_-7Eouster_cgi-2Dbin_papers_threads.pdf&d=BQICAg&c=Hw-EJUFt2_D9PK5csBJ29kRV40HqSDXWTLPyZ6W8u84&r=4sdzHKz0eU1vXqaUySVmyA&m=iyUc8eXmiD7L89LghmMd5hdgVupHEDfyZBXpjyiE-9I&s=60wp7PciYqIO8kDWvG2i0EVI8x_Mt0wPgpxjGCfkSEA&e=
>>>>>>>>>>> 
>>>>>>>>>>> 
>>>>>>>>>>>> Michael
>>>>>>>>>>>> 
>>>>>>>>>>>> On Wed, Nov 11, 2015 at 8:10 PM, Kinney, Michael D <
>>>>>>>>>>>> [email protected]> wrote:
>>>>>>>>>>>> 
>>>>>>>>>>>>> Michael,
>>>>>>>>>>>>> 
>>>>>>>>>>>>> A periodic event timer at 30 times a second should not cause
>>>> pauses
>>>>>>>>>>>>> forever, unless the action you are performing in the event
>>>>>>> notification
>>>>>>>>>>>>> function takes more than 1/30 of a second to complete.  You
>>>> should
>>>>>>> be
>>>>>>>>>>> able
>>>>>>>>>>>>> to just add a periodic event handler that does nothing, so you
>>>> can
>>>>>>>>>>> measure
>>>>>>>>>>>>> what the overhead is.
>>>>>>>>>>>>> 
>>>>>>>>>>>>> Another option is to use the performance counter in the
>> TimerLib
>>>>>>> each
>>>>>>>>>>> time
>>>>>>>>>>>>> a Blt() is called (GetPerformanceCounterProperties() and
>>>>>>>>>>>>> GetPerformanceCounter()).  When Blt() is called frequently, the
>>>>>>> amount
>>>>>>>>>>> of
>>>>>>>>>>>>> time since last vsync will have elapsed, and you can go the
>> vsync
>>>>>>> action
>>>>>>>>>>>>> within the Blt() call.  If you also set a one shot timer event,
>>>> so
>>>>>>> if
>>>>>>>>>>> the
>>>>>>>>>>>>> last call to Blt() did not do a vsync and there are no more
>> Blt()
>>>>>>> calls,
>>>>>>>>>>>>> 1/30th of a second later, the vsync action can be done.  Every
>>>> time
>>>>>>>>>>> Blt()
>>>>>>>>>>>>> is called, the one shot timer can be re-armed.  This way, the
>> one
>>>>>>> shot
>>>>>>>>>>>>> timer event is not actually executed very often.
>>>>>>>>>>>>> 
>>>>>>>>>>>>> Mike
>>>>>>>>>>>>> 
>>>>>>>>>>>>>> -----Original Message-----
>>>>>>>>>>>>>> From: edk2-devel [mailto:[email protected]] On
>>>>>>> Behalf Of
>>>>>>>>>>>>> Michael Zimmermann
>>>>>>>>>>>>>> Sent: Wednesday, November 11, 2015 12:32 AM
>>>>>>>>>>>>>> To: [email protected]
>>>>>>>>>>>>>> Subject: [edk2] EFI GOP with manual vsync trigger
>>>>>>>>>>>>>> 
>>>>>>>>>>>>>> Hi,
>>>>>>>>>>>>>> 
>>>>>>>>>>>>>> my Graphics HW uses a manual vsync trigger. That means that
>>>> after
>>>>>>>>>>> drawing
>>>>>>>>>>>>>> to the framebuffer I need to manually trigger vsync(you can
>>>>>>> compare it
>>>>>>>>>>> to
>>>>>>>>>>>>>> switching between double buffers).
>>>>>>>>>>>>>> 
>>>>>>>>>>>>>> The problem is that UEFI's GraphicsOutputProtocol(GOP) doesn't
>>>>>>> take
>>>>>>>>>>> care
>>>>>>>>>>>>> of
>>>>>>>>>>>>>> HW that needs a flush.
>>>>>>>>>>>>>> While issuing the trigger after every Blt Operation works,
>> this
>>>>>>>>>>> obviously
>>>>>>>>>>>>>> causes extremely slow rendering for applications like the
>> Shell
>>>>>>> which
>>>>>>>>>>> call
>>>>>>>>>>>>>> Blt very often(like for every character).
>>>>>>>>>>>>>> 
>>>>>>>>>>>>>> Also I can't use a timer to set the trigger(like 30times a
>>>> second)
>>>>>>>>>>> because
>>>>>>>>>>>>>> it takes too much time and the Timer Interrupt ends up
>> consuming
>>>>>>> too
>>>>>>>>>>> much
>>>>>>>>>>>>>> time and the "normal" code gets paused forever.
>>>>>>>>>>>>>> 
>>>>>>>>>>>>>> Do you have any other ideas how to handle this?
>>>>>>>>>>>>>> 
>>>>>>>>>>>>>> Thx
>>>>>>>>>>>>>> Michael
>>>>>>>>>>>>>> _______________________________________________
>>>>>>>>>>>>>> edk2-devel mailing list
>>>>>>>>>>>>>> [email protected]
>>>>>>>>>>>>>> 
>> https://urldefense.proofpoint.com/v2/url?u=https-3A__lists.01.org_mailman_listinfo_edk2-2Ddevel&d=BQICAg&c=Hw-EJUFt2_D9PK5csBJ29kRV40HqSDXWTLPyZ6W8u84&r=4sdzHKz0eU1vXqaUySVmyA&m=iyUc8eXmiD7L89LghmMd5hdgVupHEDfyZBXpjyiE-9I&s=31tD1YVkelbWB8njOCusaOe0MPbnDWaBzkwrYlfpysw&e=
>>>>>>>>>>>>> 
>>>>>>>>>>>> _______________________________________________
>>>>>>>>>>>> edk2-devel mailing list
>>>>>>>>>>>> [email protected]
>>>>>>>>>>>> 
>> https://urldefense.proofpoint.com/v2/url?u=https-3A__lists.01.org_mailman_listinfo_edk2-2Ddevel&d=BQICAg&c=Hw-EJUFt2_D9PK5csBJ29kRV40HqSDXWTLPyZ6W8u84&r=4sdzHKz0eU1vXqaUySVmyA&m=iyUc8eXmiD7L89LghmMd5hdgVupHEDfyZBXpjyiE-9I&s=31tD1YVkelbWB8njOCusaOe0MPbnDWaBzkwrYlfpysw&e=
>>>>>>>>>>> 
>>>>>>>>>>> 
>>>>>>>>>> _______________________________________________
>>>>>>>>>> edk2-devel mailing list
>>>>>>>>>> [email protected]
>>>>>>>>>> 
>> https://urldefense.proofpoint.com/v2/url?u=https-3A__lists.01.org_mailman_listinfo_edk2-2Ddevel&d=BQICAg&c=Hw-EJUFt2_D9PK5csBJ29kRV40HqSDXWTLPyZ6W8u84&r=4sdzHKz0eU1vXqaUySVmyA&m=iyUc8eXmiD7L89LghmMd5hdgVupHEDfyZBXpjyiE-9I&s=31tD1YVkelbWB8njOCusaOe0MPbnDWaBzkwrYlfpysw&e=
>>>>>>>>> 
>>>>>>>>> _______________________________________________
>>>>>>>>> edk2-devel mailing list
>>>>>>>>> [email protected]
>>>>>>>>> 
>> https://urldefense.proofpoint.com/v2/url?u=https-3A__lists.01.org_mailman_listinfo_edk2-2Ddevel&d=BQICAg&c=Hw-EJUFt2_D9PK5csBJ29kRV40HqSDXWTLPyZ6W8u84&r=4sdzHKz0eU1vXqaUySVmyA&m=iyUc8eXmiD7L89LghmMd5hdgVupHEDfyZBXpjyiE-9I&s=31tD1YVkelbWB8njOCusaOe0MPbnDWaBzkwrYlfpysw&e=
>>>>>>> 
>>>>>>> 
>>>>>> 
>>>>>> 
>>>>>> 
>>>>> _______________________________________________
>>>>> edk2-devel mailing list
>>>>> [email protected]
>>>>> 
>> https://urldefense.proofpoint.com/v2/url?u=https-3A__lists.01.org_mailman_listinfo_edk2-2Ddevel&d=BQICAg&c=Hw-EJUFt2_D9PK5csBJ29kRV40HqSDXWTLPyZ6W8u84&r=4sdzHKz0eU1vXqaUySVmyA&m=iyUc8eXmiD7L89LghmMd5hdgVupHEDfyZBXpjyiE-9I&s=31tD1YVkelbWB8njOCusaOe0MPbnDWaBzkwrYlfpysw&e=
>>>> 
>>>> 
>>> _______________________________________________
>>> edk2-devel mailing list
>>> [email protected]
>>> 
>> https://urldefense.proofpoint.com/v2/url?u=https-3A__lists.01.org_mailman_listinfo_edk2-2Ddevel&d=BQICAg&c=Hw-EJUFt2_D9PK5csBJ29kRV40HqSDXWTLPyZ6W8u84&r=4sdzHKz0eU1vXqaUySVmyA&m=iyUc8eXmiD7L89LghmMd5hdgVupHEDfyZBXpjyiE-9I&s=31tD1YVkelbWB8njOCusaOe0MPbnDWaBzkwrYlfpysw&e=
>> 
>> 
> _______________________________________________
> edk2-devel mailing list
> [email protected]
> https://lists.01.org/mailman/listinfo/edk2-devel

_______________________________________________
edk2-devel mailing list
[email protected]
https://lists.01.org/mailman/listinfo/edk2-devel

Reply via email to