+/**\r
+ Compress the data buffer but do not modify the original buffer.\r
+\r
+ The compressed data is directly send to the debug channel.\r
+ Compressing in place doesn't work because the data may become larger\r
+ during compressing phase. ("3 3 ..." --> "3 3 0 ...")\r
+ The routine is expected to be called three times:\r
+ 1. Compute the length of the compressed data buffer;\r
+ 2. Compute the CRC of the compressed data buffer;\r
+ 3. Compress the data and send to the debug channel.\r
+\r
+ @param[in] Handle The debug channel handle to send the compressed data buffer.\r
+ @param[in] Data The data buffer.\r
+ @param[in] Length The length of the data buffer.\r
+ @param[in] Send TRUE to send the compressed data buffer.\r
+ @param[out] CompressedLength Return the length of the compressed data buffer.\r
+ It may be larger than the Length in some cases.\r
+ @param[out] CompressedCrc Return the CRC of the compressed data buffer.\r
+**/\r
+VOID\r
+CompressData (\r
+ IN DEBUG_PORT_HANDLE Handle,\r
+ IN UINT8 *Data,\r
+ IN UINT8 Length,\r
+ IN BOOLEAN Send,\r
+ OUT UINTN *CompressedLength, OPTIONAL\r
+ OUT UINT16 *CompressedCrc OPTIONAL\r
+ )\r
+{\r
+ UINTN Index;\r
+ UINT8 LastChar;\r
+ UINT8 LastCharCount;\r
+ UINT8 CurrentChar;\r
+ UINTN CompressedIndex;\r
+\r
+ ASSERT (Length > 0);\r
+ LastChar = Data[0] + 1; // Just ensure it's different from the first byte.\r
+ LastCharCount = 0;\r
+\r
+ for (Index = 0, CompressedIndex = 0; Index <= Length; Index++) {\r
+ if (Index < Length) {\r
+ CurrentChar = Data[Index];\r
+ } else {\r
+ CurrentChar = (UINT8) LastChar + 1; // just ensure it's different from LastChar\r
+ }\r
+ if (LastChar != CurrentChar) {\r
+ if (LastCharCount == 1) {\r
+ CompressedIndex++;\r
+ if (CompressedCrc != NULL) {\r
+ *CompressedCrc = CalculateCrc16 (&LastChar, 1, *CompressedCrc);\r
+ }\r
+ if (Send) {\r
+ DebugPortWriteBuffer (Handle, &LastChar, 1);\r
+ }\r
+ \r
+ } else if (LastCharCount >= 2) {\r
+ CompressedIndex += 3;\r
+ LastCharCount -= 2;\r
+ if (CompressedCrc != NULL) {\r
+ *CompressedCrc = CalculateCrc16 (&LastChar, 1, *CompressedCrc);\r
+ *CompressedCrc = CalculateCrc16 (&LastChar, 1, *CompressedCrc);\r
+ *CompressedCrc = CalculateCrc16 (&LastCharCount, 1, *CompressedCrc);\r
+ }\r
+ if (Send) {\r
+ DebugPortWriteBuffer (Handle, &LastChar, 1);\r
+ DebugPortWriteBuffer (Handle, &LastChar, 1);\r
+ DebugPortWriteBuffer (Handle, &LastCharCount, 1);\r
+ }\r
+ }\r
+ LastCharCount = 0;\r
+ }\r
+ LastCharCount++;\r
+ LastChar = CurrentChar;\r
+ }\r
+\r
+ if (CompressedLength != NULL) {\r
+ *CompressedLength = CompressedIndex;\r
+ }\r
+}\r
+\r