}\r
return (NULL);\r
}\r
+/**\r
+ This is a find and replace function. it will return the NewString as a copy of \r
+ SourceString with each instance of FindTarget replaced with ReplaceWith.\r
+\r
+ If the string would grow bigger than NewSize it will halt and return error.\r
+\r
+ @param[in] SourceString String with source buffer\r
+ @param[in][out] NewString String with resultant buffer\r
+ @param[in] NewSize Size in bytes of NewString\r
+ @param[in] FindTarget String to look for\r
+ @param[in[ ReplaceWith String to replace FindTarget with\r
+\r
+ @retval EFI_INVALID_PARAMETER SourceString was NULL\r
+ @retval EFI_INVALID_PARAMETER NewString was NULL\r
+ @retval EFI_INVALID_PARAMETER FindTarget was NULL\r
+ @retval EFI_INVALID_PARAMETER ReplaceWith was NULL\r
+ @retval EFI_INVALID_PARAMETER FindTarget had length < 1\r
+ @retval EFI_INVALID_PARAMETER SourceString had length < 1\r
+ @retval EFI_BUFFER_TOO_SMALL NewSize was less than the minimum size to hold \r
+ the new string (truncation occurred)\r
+ @retval EFI_SUCCESS the string was sucessfully copied with replacement\r
+**/\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+CopyReplace(\r
+ IN CHAR16 CONST *SourceString,\r
+ IN CHAR16 *NewString,\r
+ IN UINTN NewSize,\r
+ IN CONST CHAR16 *FindTarget,\r
+ IN CONST CHAR16 *ReplaceWith\r
+ ){\r
+ if ( (SourceString == NULL)\r
+ || (NewString == NULL)\r
+ || (FindTarget == NULL)\r
+ || (ReplaceWith == NULL)\r
+ || (StrLen(FindTarget) < 1)\r
+ || (StrLen(SourceString) < 1)\r
+ ){\r
+ return (EFI_INVALID_PARAMETER);\r
+ }\r
+ NewString = SetMem16(NewString, NewSize, L'\0');\r
+ while (*SourceString != L'\0') {\r
+ if (StrnCmp(SourceString, FindTarget, StrLen(FindTarget)) == 0) {\r
+ SourceString += StrLen(FindTarget);\r
+ if (StrSize(NewString) + (StrLen(ReplaceWith)*sizeof(CHAR16)) > NewSize) {\r
+ return (EFI_BUFFER_TOO_SMALL);\r
+ }\r
+ StrCat(NewString, ReplaceWith);\r
+ } else {\r
+ if (StrSize(NewString) + sizeof(CHAR16) > NewSize) {\r
+ return (EFI_BUFFER_TOO_SMALL);\r
+ }\r
+ StrnCat(NewString, SourceString, 1);\r
+ SourceString++;\r
+ }\r
+ }\r
+ return (EFI_SUCCESS);\r
+}\r
\r
/**\r
Print at a specific location on the screen.\r
){\r
VA_LIST Marker;\r
UINTN BufferSize;\r
- CHAR16 *Buffer;\r
+ CHAR16 *PostReplaceFormat;\r
+ CHAR16 *PostReplaceFormat2;\r
UINTN Return;\r
INT32 CurrentCol;\r
INT32 CurrentRow;\r
EFI_STATUS Status;\r
+ UINTN NormalAttribute;\r
+ CHAR16 *ResumeLocation;\r
+ CHAR16 *FormatWalker;\r
+\r
+ VA_START (Marker, Format);\r
\r
BufferSize = (PcdGet32 (PcdUefiLibMaxPrintBufferSize) + 1) * sizeof (CHAR16);\r
- Buffer = AllocateZeroPool (BufferSize);\r
- ASSERT (Buffer != NULL);\r
+ PostReplaceFormat = AllocateZeroPool (BufferSize);\r
+ ASSERT (PostReplaceFormat != NULL);\r
+ PostReplaceFormat2 = AllocateZeroPool (BufferSize);\r
+ ASSERT (PostReplaceFormat2 != NULL);\r
\r
- VA_START (Marker, Format);\r
- Return = UnicodeVSPrint (Buffer, BufferSize, Format, Marker);\r
+ //\r
+ // Back and forth each time fixing up 1 of our flags...\r
+ //\r
+ Status = CopyReplace(Format, PostReplaceFormat, BufferSize, L"%N", L"%%N");\r
+ ASSERT_EFI_ERROR(Status);\r
+ Status = CopyReplace(PostReplaceFormat, PostReplaceFormat2, BufferSize, L"%E", L"%%E");\r
+ ASSERT_EFI_ERROR(Status);\r
+ Status = CopyReplace(PostReplaceFormat2, PostReplaceFormat, BufferSize, L"%H", L"%%H");\r
+ ASSERT_EFI_ERROR(Status);\r
+ Status = CopyReplace(PostReplaceFormat, PostReplaceFormat2, BufferSize, L"%B", L"%%B");\r
+ ASSERT_EFI_ERROR(Status);\r
+ Status = CopyReplace(PostReplaceFormat2, PostReplaceFormat, BufferSize, L"%V", L"%%V");\r
+ ASSERT_EFI_ERROR(Status);\r
+\r
+ //\r
+ // Use the last buffer from replacing to print from...\r
+ //\r
+ Return = UnicodeVSPrint (PostReplaceFormat2, BufferSize, PostReplaceFormat, Marker);\r
+\r
+ FreePool(PostReplaceFormat);\r
\r
if (Col != -1 && Row != -1) {\r
CurrentCol = gST->ConOut->Mode->CursorColumn;\r
CurrentRow = gST->ConOut->Mode->CursorRow;\r
Status = gST->ConOut->SetCursorPosition(gST->ConOut, Col, Row);\r
ASSERT_EFI_ERROR(Status);\r
- Status = gST->ConOut->OutputString(gST->ConOut, Buffer);\r
+ } else {\r
+ CurrentCol = 0;\r
+ CurrentRow = 0;\r
+ }\r
+\r
+ NormalAttribute = gST->ConOut->Mode->Attribute;\r
+ FormatWalker = PostReplaceFormat2;\r
+ while (*FormatWalker != L'\0') {\r
+ //\r
+ // Find the next attribute change request\r
+ //\r
+ ResumeLocation = StrStr(FormatWalker, L"%");\r
+ if (ResumeLocation != NULL) {\r
+ *ResumeLocation = L'\0';\r
+ }\r
+ //\r
+ // print the current FormatWalker string\r
+ //\r
+ Status = gST->ConOut->OutputString(gST->ConOut, FormatWalker);\r
ASSERT_EFI_ERROR(Status);\r
+ //\r
+ // update the attribute\r
+ //\r
+ if (ResumeLocation != NULL) {\r
+ switch (*(ResumeLocation+1)) {\r
+ case (L'N'):\r
+ gST->ConOut->SetAttribute(gST->ConOut, NormalAttribute);\r
+ break;\r
+ case (L'E'):\r
+ gST->ConOut->SetAttribute(gST->ConOut, EFI_TEXT_ATTR(EFI_YELLOW, ((NormalAttribute&(BIT4|BIT5|BIT6))>>4)));\r
+ break;\r
+ case (L'H'):\r
+ gST->ConOut->SetAttribute(gST->ConOut, EFI_TEXT_ATTR(EFI_WHITE, ((NormalAttribute&(BIT4|BIT5|BIT6))>>4)));\r
+ break;\r
+ case (L'B'):\r
+ gST->ConOut->SetAttribute(gST->ConOut, EFI_TEXT_ATTR(EFI_BLUE, ((NormalAttribute&(BIT4|BIT5|BIT6))>>4)));\r
+ break;\r
+ case (L'V'):\r
+ gST->ConOut->SetAttribute(gST->ConOut, EFI_TEXT_ATTR(EFI_GREEN, ((NormalAttribute&(BIT4|BIT5|BIT6))>>4)));\r
+ break;\r
+ default:\r
+ ASSERT(FALSE);\r
+ break;\r
+ }\r
+ } else {\r
+ //\r
+ // reset to normal now...\r
+ //\r
+ gST->ConOut->SetAttribute(gST->ConOut, NormalAttribute);\r
+ break;\r
+ }\r
+\r
+ //\r
+ // update FormatWalker to Resume + 2 (skip the % and the indicator)\r
+ //\r
+ FormatWalker = ResumeLocation + 2;\r
+ }\r
+ \r
+ if (Col != -1 && Row != -1) {\r
Status = gST->ConOut->SetCursorPosition(gST->ConOut, CurrentCol, CurrentRow);\r
ASSERT_EFI_ERROR(Status);\r
- } else {\r
- Status = gST->ConOut->OutputString(gST->ConOut, Buffer);\r
- ASSERT_EFI_ERROR(Status);\r
}\r
\r
- FreePool(Buffer);\r
+ FreePool(PostReplaceFormat2);\r
+\r
return (Return);\r
}
\ No newline at end of file