+ ASSERT ((UINTN)ThunkContext->RealModeBuffer < 0x100000);\r
+ ASSERT (ThunkContext->RealModeBufferSize >= m16Size);\r
+ ASSERT ((UINTN)ThunkContext->RealModeBuffer + m16Size <= 0x100000);\r
+ ASSERT (((UINTN)ThunkContext->RealModeBuffer & 0x0f) == 0);\r
+\r
+ CopyMem (ThunkContext->RealModeBuffer, &m16Start, m16Size);\r
+\r
+ //\r
+ // Point RealModeGdt to the GDT to be used in transition\r
+ //\r
+ // RealModeGdt[0]: Reserved as NULL descriptor\r
+ // RealModeGdt[1]: Code Segment\r
+ // RealModeGdt[2]: Data Segment\r
+ // RealModeGdt[3]: Call Gate\r
+ //\r
+ RealModeGdt = (IA32_SEGMENT_DESCRIPTOR*)(\r
+ (UINTN)ThunkContext->RealModeBuffer + m16Gdt);\r
+\r
+ //\r
+ // Update Code & Data Segment Descriptor\r
+ //\r
+ RealModeGdt[1].Bits.BaseLow =\r
+ (UINT32)(UINTN)ThunkContext->RealModeBuffer & ~0xf;\r
+ RealModeGdt[1].Bits.BaseMid =\r
+ (UINT32)(UINTN)ThunkContext->RealModeBuffer >> 16;\r
+\r
+ //\r
+ // Update transition code entry point offset\r
+ //\r
+ *(UINT32*)((UINTN)ThunkContext->RealModeBuffer + mTransition) +=\r
+ (UINT32)(UINTN)ThunkContext->RealModeBuffer & 0xf;\r
+\r
+ //\r
+ // Update Segment Limits for both Code and Data Segment Descriptors\r
+ //\r
+ if ((ThunkContext->ThunkAttributes & THUNK_ATTRIBUTE_BIG_REAL_MODE) == 0) {\r
+ //\r
+ // Set segment limits to 64KB\r
+ //\r
+ RealModeGdt[1].Bits.LimitHigh = 0;\r
+ RealModeGdt[1].Bits.G = 0;\r
+ RealModeGdt[2].Bits.LimitHigh = 0;\r
+ RealModeGdt[2].Bits.G = 0;\r
+ }\r
+\r
+ //\r
+ // Update GDTBASE for this thunk context\r
+ //\r
+ *(VOID**)((UINTN)ThunkContext->RealModeBuffer + m16GdtrBase) = RealModeGdt;\r
+\r
+ //\r
+ // Update Thunk Attributes\r
+ //\r
+ *(UINT32*)((UINTN)ThunkContext->RealModeBuffer + mThunk16Attr) =\r
+ ThunkContext->ThunkAttributes;\r