HI Andrew Fish,
Thanks for the quick update.
Still I am not clear on few things.
1. When exactly we go for Locking or why we need it ?
If, we change the TPL Level means we need to take care of restoring it.That
is fine
Similarly to achieve the same thing in core code we implemented locking
mechanism.correct  ? (locks are used in core code only)

"Thus blocking events prevents reentrancy, and is used for Locks." Can it
be elaborated more?

3. Nothing will be interrupted when we switch b/w TPL Levels its all about
how we program.is it like that ?
  So,below lines in the Spec are just telling us how to use those TPL
Levels ?

Interrupts code executing below TPL_CALLBACK level.Long term operations
(such as file system operations and disk I/O) can occur at this level.

 Interrupts code executing below TPL_NOTIFY level. Blocking is not allowed
at this level. Code executes to completion and returns. If code requires
more processing, it needs to signal an event to wait to obtain control
again at whatever level it requires. This level is typically used to
process low level IO to or from a device.

Thanks,
Chinni.



On Tue, Jun 30, 2015 at 11:41 AM, <edk2-devel-requ...@lists.sourceforge.net>
wrote:

> Send edk2-devel mailing list submissions to
>         edk2-devel@lists.sourceforge.net
>
> To subscribe or unsubscribe via the World Wide Web, visit
>         https://lists.sourceforge.net/lists/listinfo/edk2-devel
> or, via email, send a message with subject or body 'help' to
>         edk2-devel-requ...@lists.sourceforge.net
>
> You can reach the person managing the list at
>         edk2-devel-ow...@lists.sourceforge.net
>
> When replying, please edit your Subject line so it is more specific
> than "Re: Contents of edk2-devel digest..."
>
>
> Today's Topics:
>
>    1. Re: Few doubts on code execution (Andrew Fish)
>    2. [patch] SecurityPkg: Calculate the length of the String.
>       (Zhang Lubo)
>    3. Re: [MinnowBoard] UART and COM ports problem (Anteja Vuk Macek)
>    4. [Patch] MdeModulePkg: Merge GCD range before convert it to
>       EFI memory (Liming Gao)
>
>
> ----------------------------------------------------------------------
>
> Message: 1
> Date: Mon, 29 Jun 2015 22:25:15 -0700
> From: Andrew Fish <af...@apple.com>
> Subject: Re: [edk2] Few doubts on code execution
> To: edk2-devel@lists.sourceforge.net
> Message-ID: <35fca04e-9c21-475a-b6e8-efa6fa633...@apple.com>
> Content-Type: text/plain; charset=utf-8
>
>
> > On Jun 29, 2015, at 10:05 PM, D chinni babu <d.chinnib...@gmail.com>
> wrote:
> >
> > Hi All,
> > I have few questions on UEFI Code execution.Please help me to
> understand  UEFI in a better way.
> >
> > 1) What is the need of locking mechanism and Task Priority Levels in
> UEFI when there is no multi process execution in boot time?
>
> UEFI is an event model. While this presentation is not related to UEFI in
> any way it is useful in explaining why we picked a simplistic event model
> for EFI.
> https://web.stanford.edu/~ouster/cgi-bin/papers/threads.pdf
>
> > More insight ,As Per my understanding we have only one interrupt which
> is Timer interrupt which can halt the normal execution to check for Timer
> events.If any Timer event needs to signal it will can and exit.
> > TPL is Raising to TPL_HIGH_LEVEL -1  when we look for timer events in
> the Queue.
> > My doubt is when exactly Locking mechanism becomes handy?
> > TPL_APPLICATION is the normal default level execution and when we create
> a event type other than EVT_TIMER , it will be executed only when we signal
> the event (directly by us or indirectly by core code) when means core code
> will look into the link-list and call the notification function.Everything
> looks like Linear execution.
> >
>
> You are thinking about a thread model, UEFI is an event module. There is
> just the main program (what ever driver, app, is running) and events. There
> is no scheduler, the main flow owns the system, and events can fire. Thus
> blocking events prevents reentrancy, and is used for Locks. If you look at
> Table 23, you will see that most interfaces, and services have TPL
> restrictions. Thus you only have to raise hight enough to block being
> called.
>
> >
> > 2)  In locking mechanism and Task Priority Levels Core code we are using
> ASSERT messages to detect the errors that means these wont be
> detected/reported in Release build.correct ? if it is so ,in release build
> when we have error in TPL_LEVEL change or in Locking mechanism and there is
> no hardware or software issue found in Firmware execution in real time ,we
> wont be able to detect .correct ?
> >
>
> Don?t bad TPL operation is ?undefined behavior? per the EFI spec and the
> system may crash. It is a bug in your code, so the DEBUG builds ASSERT to
> let you know. The release builds try to keep running. There is not much
> more they could do, well I guess they could log an error.
>
> >  3) In UEFI Spec Table 22 .we have a description for the TPLS Levels.
> >
> > Interrupts code executing below TPL_CALLBACK level.Long term operations
> (such as file system operations and disk I/O) can occur at this level.
> >
> > Interrupts code executing below TPL_NOTIFY level. Blocking is not
> allowed at this level. Code executes to completion and returns. If code
> requires more processing, it needs to signal an event to wait to obtain
> control again at whatever level it requires. This level is typically used
> to process low level IO to or from a device.
> >
> > I didn't seen any core code to achieve both the statements.Is there any
> core code to differentiate the TPL Levels and to stop one code execution
> and call the other one at different level ?
> >
>
> It is an event model, so the person writing the event has to yield the
> system back. If you put a CpuDeadLoop() in an event handler you will crash
> the system.
>
> Thanks,
>
> Andrew Fish
>
> > Please help to clarify these things for better understanding of UEFI.
> >
> > Thanks,
> > Chinni.
> >
> >
> ------------------------------------------------------------------------------
> > Don't Limit Your Business. Reach for the Cloud.
> > GigeNET's Cloud Solutions provide you with the tools and support that
> > you need to offload your IT needs and focus on growing your business.
> > Configured For All Businesses. Start Your Cloud Today.
> >
> https://www.gigenetcloud.com/_______________________________________________
> > edk2-devel mailing list
> > edk2-devel@lists.sourceforge.net
> > https://lists.sourceforge.net/lists/listinfo/edk2-devel
>
>
>
>
> ------------------------------
>
> Message: 2
> Date: Tue, 30 Jun 2015 13:26:55 +0800
> From: Zhang Lubo <lubo.zh...@intel.com>
> Subject: [edk2] [patch] SecurityPkg: Calculate the length of the
>         String.
> To: edk2-devel@lists.sourceforge.net;
> Message-ID: <0147d2d0-c351-42fc-8bae-56e5d755e81c@LUBOZHAN-MOBL.local>
> Content-Type: text/plain;
>
> When the two concatenated strings are both not null, the total length in
> bytes of them should calculate the character '\0' once.
>
> Contributed-under: TianoCore Contribution Agreement 1.0
> Signed-off-by: Zhang Lubo <lubo.zh...@intel.com>
> ---
>  .../UserIdentification/UserProfileManagerDxe/UserProfileModify.c        |
> 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git
> a/SecurityPkg/UserIdentification/UserProfileManagerDxe/UserProfileModify.c
> b/SecurityPkg/UserIdentification/UserProfileManagerDxe/UserProfileModify.c
> index 67fc300..a0eb4af 100644
> ---
> a/SecurityPkg/UserIdentification/UserProfileManagerDxe/UserProfileModify.c
> +++
> b/SecurityPkg/UserIdentification/UserProfileManagerDxe/UserProfileModify.c
> @@ -336,11 +336,11 @@ AddStr (
>
>    if (*Source1 == NULL) {
>      StrLength = StrSize (Source2);
>    } else {
>      StrLength  = StrSize (*Source1);
> -    StrLength += StrSize (Source2) -1;
> +    StrLength += StrSize (Source2) - 2;
>    }
>
>    TmpStr     = AllocateZeroPool (StrLength);
>    ASSERT (TmpStr != NULL);
>
> --
> 1.9.5.msysgit.1
>
>
>
>
>
> ------------------------------
>
> Message: 3
> Date: Tue, 30 Jun 2015 07:33:25 +0200
> From: Anteja Vuk Macek <anteja...@dolotron.com>
> Subject: Re: [edk2] [MinnowBoard] UART and COM ports problem
> To: "Rouzanov, Ivan" <ivan.rouza...@intel.com>,         "edk2-devel(email
>         list)" <edk2-devel@lists.sourceforge.net>,      elinux-minnowboard
>         <elinux-minnowbo...@lists.elinux.org>
> Message-ID:
>         <
> caoptr2dmna+44tghqfblwrtmp--ug+j5qut5hwq0k3ckxni...@mail.gmail.com>
> Content-Type: text/plain; charset="utf-8"
>
> Hi Ivan,
>
> Thank you for advice, but I want two COM ports.  I found  LPC_DEV.ASL
> ACPI_table  in Vlv2TbltDeviceRefCodePkg where was ASL code for the device
> IUR3  HID - PNP0501.
>
> Device(IUR3) // Internal UART
> {
>   Name(_HID, EISAID("PNP0501"))
>
>   Name(_UID,1)
>
>   // Status Method for internal UART
>
>   Method(_STA,0,Serialized)
>   {
>     // Only report resources to the OS if internal UART is
>     // not set to Disabled in BIOS Setup.
>
>     If(LEqual(USEL,0))
>     {
>       If(LEqual(PU1E,1))
>       {
>         Store(1,UI3E) // Enable IRQ3 for UART
>         Store(1,UI4E) // Enable IRQ4 for UART
>         Store(1,C1EN) // Enable UART
>         Return(0x000F)
>       }
>     }
>
>     Return(0x0000)
>   }
>
>   // Disable Method for internal UART
>
>   Method(_DIS,0,Serialized)
>   {
>     Store(0,UI3E)
>     Store(0,UI4E)
>     Store(0,C1EN)
>   }
>
>   // Current Resource Setting Method for internal UART
>
>   Method(_CRS,0,Serialized)
>   {
>     // Create the Buffer that stores the Resources to
>     // be returned.
>
>     Name(BUF0,ResourceTemplate()
>     {
>       IO(Decode16,0x03F8,0x03F8,0x01,0x08)
>       IRQNoFlags() {3}
>     })
>
>     Name(BUF1,ResourceTemplate()
>     {
>       IO(Decode16,0x03F8,0x03F8,0x01,0x08)
>       IRQNoFlags() {4}
>     })
>
>     If (LLessEqual(SRID, 0x04))
>     {
>       Return(BUF0)
>     } Else
>     {
>       Return(BUF1)
>     }
>   }
> }
>
> I want to make second IUR device.  I don't know value of variables : SEL,
> PU1E, UI3E, UI4E and C1EN  and where it was defined.  Also,  I would like
> to know what I need to change to write ASL code for second IURx device.
> Best regards,
>
> Anteja
>
> >On Thu, Jun 25, 2015 at 11:16 AM, Rouzanov, Ivan <ivan.rouza...@intel.com
> >
> wrote:
>
> > >Anteja,
> > >
> > >As far as I understand we have 2 UARTs but only one follows legacy
> > COM-interface and the other one does not so Windows inbox driver
> serial.sys
> > does not work with it so you only have one COM port.
> > >(Basically COMx is just a symbolic link serial.sys creates to point to
> > its device object, so if it does not service a device like in the case of
> > the second HSUART, then it is not a COM-port).
> > >f you need to use COM-port and have ability to debug, I'd suggest to use
> > Ethernet for debugging and free up COM1 for your other needs.
> > >
> > >I hope this helps.
> > >Best regards,
> > >van Rouzanov.
> > >
> > >
> > >
> > >Message: 3
> > >Date: Wed, 24 Jun 2015 10:06:02 +0200
> > >From: Anteja Vuk Macek <anteja...@dolotron.com>
> > >To: EDK2 email list <edk2-devel@lists.sourceforge.net>,  MinnowMax
> > >       Community <elinux-minnowbo...@lists.elinux.org>
> > >Subject: [MinnowBoard] UART and COM ports problem
> > >Message-ID:
> > >       <
> > caoptr2bqg0h5kt8dogxr60t3++i4tchpfchyo6qwqkykqgw...@mail.gmail.com>
> > >Content-Type: text/plain; charset="utf-8"
> > >
> > >Hi all,
> > >
> > >On MinnowMax I work  on Windows 8.1 with UART.
> > > In BIOS Setup I enable UART.   In  LSS & SCC Configuration menu in BIOS
> > >Setup I enable : LSS HSUART #1 Support  , LSS HSUART #1 FlowCtrl  , LSS
> > HSUART #2 Support  , and LSS HSUART #2 FlowCtrl .  But I don't know if I
> > need to in BIOS Setup in Miscellaneous configuration  set  UART
> >interface
> > on  Super IO UART, for now I set  Internal UART for UART interface.
> > >I install Intel driver (
> > >
> >
> https://downloadcenter.intel.com/download/24228/Intel-embedded-drivers-for-Windows-8-1-32-bit-
> > >)
> > >and I got two UART controllers.
> > >
> > >Problem :
> > >Problem is that I have only one COM port ( COM1)  and it is for
> > debugging.  I looking in inf (iaiouart.inf ) file of driver for which
> > device is , and I find APCI/INT33BC device.  The COM1 is device
> > >APCI/PNP0501 .
> > >
> > >What I need to do to get COM 2 device ?  I saw  BaseSerialPortLib 16550
> > module in  MdeModulePkg/Library for what it is this module.  Need I add
> > some module for UART or Serial port in fdf (PlatformPkg.fdf ) file to get
> > >COM2 device, or add  COM2  in ACPI_table? Where I can find ACPI_table in
> > source of firmware?
> > >
> > >Best regards,
> > >
> > >Anteja
> > >
> -------------- next part --------------
> An HTML attachment was scrubbed...
>
> ------------------------------
>
> Message: 4
> Date: Tue, 30 Jun 2015 14:11:47 +0800
> From: Liming Gao <liming....@intel.com>
> Subject: [edk2] [Patch] MdeModulePkg: Merge GCD range before convert
>         it to   EFI memory
> To: edk2-devel@lists.sourceforge.net
> Message-ID: <1435644707-33220-1-git-send-email-liming....@intel.com>
>
> GCD Range is byte address. EFI memory range is page address. To make sure
> GCD range is converted to EFI memory range, the following things are added:
> 1. Merge adjacent GCD range first.
> 2. Add ASSERT check on GCD range alignment.
>
> Contributed-under: TianoCore Contribution Agreement 1.0
> Signed-off-by: Liming Gao <liming....@intel.com>
> ---
>  MdeModulePkg/Core/Dxe/Mem/Page.c | 78
> +++++++++++++++++++++++++++++++---------
>  1 file changed, 61 insertions(+), 17 deletions(-)
>
> diff --git a/MdeModulePkg/Core/Dxe/Mem/Page.c
> b/MdeModulePkg/Core/Dxe/Mem/Page.c
> index a285529..9dbb85d 100644
> --- a/MdeModulePkg/Core/Dxe/Mem/Page.c
> +++ b/MdeModulePkg/Core/Dxe/Mem/Page.c
> @@ -1541,10 +1541,11 @@ CoreGetMemoryMap (
>    UINTN                             BufferSize;
>    UINTN                             NumberOfEntries;
>    LIST_ENTRY                        *Link;
>    MEMORY_MAP                        *Entry;
>    EFI_GCD_MAP_ENTRY                 *GcdMapEntry;
> +  EFI_GCD_MAP_ENTRY                 MergeGcdMapEntry;
>    EFI_MEMORY_TYPE                   Type;
>    EFI_MEMORY_DESCRIPTOR             *MemoryMapStart;
>
>    //
>    // Make sure the parameters are valid
> @@ -1652,29 +1653,53 @@ CoreGetMemoryMap (
>      // existing descriptor if they are adjacent and have the same
> attributes
>      //
>      MemoryMap = MergeMemoryMapDescriptor (MemoryMapStart, 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) &&
> -        ((GcdMapEntry->Attributes & EFI_MEMORY_RUNTIME) ==
> EFI_MEMORY_RUNTIME))) {
> +
> +  ZeroMem (&MergeGcdMapEntry, sizeof (MergeGcdMapEntry));
> +  GcdMapEntry = NULL;
> +  for (Link = mGcdMemorySpaceMap.ForwardLink; ; Link = Link->ForwardLink)
> {
> +    if (Link != &mGcdMemorySpaceMap) {
> +      //
> +      // Merge adjacent same type and attribute GCD memory range
> +      //
> +      GcdMapEntry = CR (Link, EFI_GCD_MAP_ENTRY, Link,
> EFI_GCD_MAP_SIGNATURE);
> +
> +      if ((MergeGcdMapEntry.Capabilities == GcdMapEntry->Capabilities) &&
> +          (MergeGcdMapEntry.Attributes == GcdMapEntry->Attributes) &&
> +          (MergeGcdMapEntry.GcdMemoryType == GcdMapEntry->GcdMemoryType)
> &&
> +          (MergeGcdMapEntry.GcdIoType == GcdMapEntry->GcdIoType)) {
> +        MergeGcdMapEntry.EndAddress  = GcdMapEntry->EndAddress;
> +        continue;
> +      }
> +    }
> +
> +    if ((MergeGcdMapEntry.GcdMemoryType == EfiGcdMemoryTypeReserved) ||
> +        ((MergeGcdMapEntry.GcdMemoryType ==
> EfiGcdMemoryTypeMemoryMappedIo) &&
> +        ((MergeGcdMapEntry.Attributes & EFI_MEMORY_RUNTIME) ==
> EFI_MEMORY_RUNTIME))) {
> +      //
> +      // Page Align GCD range is required. When it is converted to
> EFI_MEMORY_DESCRIPTOR,
> +      // it will be recorded as page PhysicalStart and NumberOfPages.
> +      //
> +      ASSERT ((MergeGcdMapEntry.BaseAddress & EFI_PAGE_MASK) == 0);
> +      ASSERT (((MergeGcdMapEntry.EndAddress -
> MergeGcdMapEntry.BaseAddress + 1) & EFI_PAGE_MASK) == 0);
> +
>        //
>        // Create EFI_MEMORY_DESCRIPTOR for every Reserved and runtime MMIO
> GCD entries
>        //
> -      MemoryMap->PhysicalStart = GcdMapEntry->BaseAddress;
> +      MemoryMap->PhysicalStart = MergeGcdMapEntry.BaseAddress;
>        MemoryMap->VirtualStart  = 0;
> -      MemoryMap->NumberOfPages = RShiftU64 ((GcdMapEntry->EndAddress -
> GcdMapEntry->BaseAddress + 1), EFI_PAGE_SHIFT);
> -      MemoryMap->Attribute     = (GcdMapEntry->Attributes &
> ~EFI_MEMORY_PORT_IO) |
> -                                (GcdMapEntry->Capabilities &
> (EFI_MEMORY_RP | EFI_MEMORY_WP | EFI_MEMORY_XP | EFI_MEMORY_RO |
> +      MemoryMap->NumberOfPages = RShiftU64 ((MergeGcdMapEntry.EndAddress
> - MergeGcdMapEntry.BaseAddress + 1), EFI_PAGE_SHIFT);
> +      MemoryMap->Attribute     = (MergeGcdMapEntry.Attributes &
> ~EFI_MEMORY_PORT_IO) |
> +                                (MergeGcdMapEntry.Capabilities &
> (EFI_MEMORY_RP | EFI_MEMORY_WP | EFI_MEMORY_XP | EFI_MEMORY_RO |
>                                  EFI_MEMORY_UC | EFI_MEMORY_UCE |
> EFI_MEMORY_WC | EFI_MEMORY_WT | EFI_MEMORY_WB));
>
> -      if (GcdMapEntry->GcdMemoryType == EfiGcdMemoryTypeReserved) {
> +      if (MergeGcdMapEntry.GcdMemoryType == EfiGcdMemoryTypeReserved) {
>          MemoryMap->Type = EfiReservedMemoryType;
> -      } else if (GcdMapEntry->GcdMemoryType ==
> EfiGcdMemoryTypeMemoryMappedIo) {
> -        if ((GcdMapEntry->Attributes & EFI_MEMORY_PORT_IO) ==
> EFI_MEMORY_PORT_IO) {
> +      } else if (MergeGcdMapEntry.GcdMemoryType ==
> EfiGcdMemoryTypeMemoryMappedIo) {
> +        if ((MergeGcdMapEntry.Attributes & EFI_MEMORY_PORT_IO) ==
> EFI_MEMORY_PORT_IO) {
>            MemoryMap->Type = EfiMemoryMappedIOPortSpace;
>          } else {
>            MemoryMap->Type = EfiMemoryMappedIO;
>          }
>        }
> @@ -1684,28 +1709,47 @@ CoreGetMemoryMap (
>        // existing descriptor if they are adjacent and have the same
> attributes
>        //
>        MemoryMap = MergeMemoryMapDescriptor (MemoryMapStart, MemoryMap,
> Size);
>      }
>
> -    if (GcdMapEntry->GcdMemoryType == EfiGcdMemoryTypePersistentMemory) {
> +    if (MergeGcdMapEntry.GcdMemoryType ==
> EfiGcdMemoryTypePersistentMemory) {
> +      //
> +      // Page Align GCD range is required. When it is converted to
> EFI_MEMORY_DESCRIPTOR,
> +      // it will be recorded as page PhysicalStart and NumberOfPages.
> +      //
> +      ASSERT ((MergeGcdMapEntry.BaseAddress & EFI_PAGE_MASK) == 0);
> +      ASSERT (((MergeGcdMapEntry.EndAddress -
> MergeGcdMapEntry.BaseAddress + 1) & EFI_PAGE_MASK) == 0);
> +
>        //
>        // Create EFI_MEMORY_DESCRIPTOR for every Persistent GCD entries
>        //
> -      MemoryMap->PhysicalStart = GcdMapEntry->BaseAddress;
> +      MemoryMap->PhysicalStart = MergeGcdMapEntry.BaseAddress;
>        MemoryMap->VirtualStart  = 0;
> -      MemoryMap->NumberOfPages = RShiftU64 ((GcdMapEntry->EndAddress -
> GcdMapEntry->BaseAddress + 1), EFI_PAGE_SHIFT);
> -      MemoryMap->Attribute     = GcdMapEntry->Attributes | EFI_MEMORY_NV |
> -                                (GcdMapEntry->Capabilities &
> (EFI_MEMORY_RP | EFI_MEMORY_WP | EFI_MEMORY_XP | EFI_MEMORY_RO |
> +      MemoryMap->NumberOfPages = RShiftU64 ((MergeGcdMapEntry.EndAddress
> - MergeGcdMapEntry.BaseAddress + 1), EFI_PAGE_SHIFT);
> +      MemoryMap->Attribute     = MergeGcdMapEntry.Attributes |
> EFI_MEMORY_NV |
> +                                (MergeGcdMapEntry.Capabilities &
> (EFI_MEMORY_RP | EFI_MEMORY_WP | EFI_MEMORY_XP | EFI_MEMORY_RO |
>                                  EFI_MEMORY_UC | EFI_MEMORY_UCE |
> EFI_MEMORY_WC | EFI_MEMORY_WT | EFI_MEMORY_WB));
>        MemoryMap->Type          = EfiPersistentMemory;
>
>        //
>        // Check to see if the new Memory Map Descriptor can be merged with
> an
>        // existing descriptor if they are adjacent and have the same
> attributes
>        //
>        MemoryMap = MergeMemoryMapDescriptor (MemoryMapStart, MemoryMap,
> Size);
>      }
> +    if (Link == &mGcdMemorySpaceMap) {
> +      //
> +      // break loop when arrive at head.
> +      //
> +      break;
> +    }
> +    if (GcdMapEntry != NULL) {
> +      //
> +      // Copy new GCD map entry for the following GCD range merge
> +      //
> +      CopyMem (&MergeGcdMapEntry, GcdMapEntry, sizeof (MergeGcdMapEntry));
> +    }
>    }
>
>    //
>    // Compute the size of the buffer actually used after all memory map
> descriptor merge operations
>    //
> --
> 1.9.5.msysgit.0
>
>
>
>
> ------------------------------
>
>
> ------------------------------------------------------------------------------
> Don't Limit Your Business. Reach for the Cloud.
> GigeNET's Cloud Solutions provide you with the tools and support that
> you need to offload your IT needs and focus on growing your business.
> Configured For All Businesses. Start Your Cloud Today.
> https://www.gigenetcloud.com/
>
> ------------------------------
>
> _______________________________________________
> edk2-devel mailing list
> edk2-devel@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/edk2-devel
>
>
> End of edk2-devel Digest, Vol 66, Issue 397
> *******************************************
>
------------------------------------------------------------------------------
Don't Limit Your Business. Reach for the Cloud.
GigeNET's Cloud Solutions provide you with the tools and support that
you need to offload your IT needs and focus on growing your business.
Configured For All Businesses. Start Your Cloud Today.
https://www.gigenetcloud.com/
_______________________________________________
edk2-devel mailing list
edk2-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/edk2-devel

Reply via email to