4 Copyright (c) 2019 - 2020, Arm Limited. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
9 #include <Stream/AmlStream.h>
11 /** Initialize a stream.
13 @param [in, out] Stream Pointer to the stream to initialize.
14 @param [in] Buffer Buffer to initialize Stream with.
15 Point to the beginning of the Buffer.
16 @param [in] MaxBufferSize Maximum size of Buffer.
17 @param [in] Direction Direction Stream is progressing
20 @retval EFI_SUCCESS The function completed successfully.
21 @retval EFI_INVALID_PARAMETER Invalid parameter.
26 IN OUT AML_STREAM
* Stream
,
28 IN UINT32 MaxBufferSize
,
29 IN EAML_STREAM_DIRECTION Direction
32 if ((Stream
== NULL
) ||
34 (MaxBufferSize
== 0) ||
35 ((Direction
!= EAmlStreamDirectionForward
) &&
36 (Direction
!= EAmlStreamDirectionBackward
))) {
38 return EFI_INVALID_PARAMETER
;
41 Stream
->Buffer
= Buffer
;
42 Stream
->MaxBufferSize
= MaxBufferSize
;
44 Stream
->Direction
= Direction
;
51 Cloning a stream means copying all the values of the input Stream
54 @param [in] Stream Pointer to the stream to clone.
55 @param [in] ClonedStream Pointer to the stream to initialize.
57 @retval EFI_SUCCESS The function completed successfully.
58 @retval EFI_INVALID_PARAMETER Invalid parameter.
63 IN CONST AML_STREAM
* Stream
,
64 OUT AML_STREAM
* ClonedStream
67 if (!IS_STREAM (Stream
) ||
68 (ClonedStream
== NULL
)) {
70 return EFI_INVALID_PARAMETER
;
73 ClonedStream
->Buffer
= Stream
->Buffer
;
74 ClonedStream
->MaxBufferSize
= Stream
->MaxBufferSize
;
75 ClonedStream
->Index
= Stream
->Index
;
76 ClonedStream
->Direction
= Stream
->Direction
;
81 /** Initialize a sub-stream from a stream.
83 A sub-stream is a stream initialized at the current position of the input
85 - the Buffer field points to the current position of the input stream;
86 - the Index field is set to 0;
87 - the MaxBufferSize field is set to the remaining size of the input stream;
88 - the direction is conserved;
90 E.g.: For a forward stream:
91 +----------------+----------------+
92 |ABCD.........XYZ| Free Space |
93 +----------------+----------------+
95 Stream: Buffer CurrPos EndOfBuff
96 Sub-stream: Buffer/CurrPos EndOfBuff
98 @param [in] Stream Pointer to the stream from which a sub-stream is
100 @param [in] SubStream Pointer to the stream to initialize.
102 @retval EFI_SUCCESS The function completed successfully.
103 @retval EFI_INVALID_PARAMETER Invalid parameter.
107 AmlStreamInitSubStream (
108 IN CONST AML_STREAM
* Stream
,
109 OUT AML_STREAM
* SubStream
112 if (!IS_STREAM (Stream
) ||
113 (SubStream
== NULL
)) {
115 return EFI_INVALID_PARAMETER
;
118 if (IS_STREAM_FORWARD (Stream
)) {
119 SubStream
->Buffer
= AmlStreamGetCurrPos (Stream
);
120 } else if (IS_STREAM_BACKWARD (Stream
)) {
121 SubStream
->Buffer
= Stream
->Buffer
;
124 return EFI_INVALID_PARAMETER
;
127 SubStream
->MaxBufferSize
= AmlStreamGetFreeSpace (Stream
);
128 SubStream
->Index
= 0;
129 SubStream
->Direction
= Stream
->Direction
;
134 /** Get the buffer of a stream.
136 @param [in] Stream Pointer to a stream.
138 @return The stream's Buffer.
144 IN CONST AML_STREAM
* Stream
147 if (!IS_STREAM (Stream
)) {
151 return Stream
->Buffer
;
154 /** Get the size of Stream's Buffer.
156 @param [in] Stream Pointer to a stream.
158 @return The Size of Stream's Buffer.
159 Return 0 if Stream is invalid.
163 AmlStreamGetMaxBufferSize (
164 IN CONST AML_STREAM
* Stream
167 if (!IS_STREAM (Stream
)) {
171 return Stream
->MaxBufferSize
;
174 /** Reduce the maximal size of Stream's Buffer (MaxBufferSize field).
176 @param [in] Stream Pointer to a stream.
177 @param [in] Diff Value to subtract to the Stream's MaxBufferSize.
178 0 < x < MaxBufferSize - Index.
180 @retval EFI_SUCCESS The function completed successfully.
181 @retval EFI_INVALID_PARAMETER Invalid parameter.
185 AmlStreamReduceMaxBufferSize (
186 IN AML_STREAM
* Stream
,
190 if (!IS_STREAM (Stream
) ||
192 ((Stream
->MaxBufferSize
- Diff
) <= Stream
->Index
)) {
194 return EFI_INVALID_PARAMETER
;
197 Stream
->MaxBufferSize
-= Diff
;
201 /** Get Stream's Index.
203 Stream's Index is incremented when writing data, reading data,
204 or moving the position in the Stream.
205 It can be seen as an index:
206 - starting at the beginning of Stream's Buffer if the stream goes forward;
207 - starting at the end of Stream's Buffer if the stream goes backward.
209 @param [in] Stream Pointer to a stream.
211 @return Stream's Index.
212 Return 0 if Stream is invalid.
217 IN CONST AML_STREAM
* Stream
220 if (!IS_STREAM (Stream
)) {
224 return Stream
->Index
;
227 /** Get Stream's Direction.
229 @param [in] Stream Pointer to a stream.
231 @return Stream's Direction.
232 Return EAmlStreamDirectionUnknown if Stream is invalid.
234 EAML_STREAM_DIRECTION
236 AmlStreamGetDirection (
237 IN CONST AML_STREAM
* Stream
240 if (!IS_STREAM (Stream
)) {
242 return EAmlStreamDirectionInvalid
;
244 return Stream
->Direction
;
247 /** Return a pointer to the current position in the stream.
249 @param [in] Stream Pointer to a stream.
251 @return The current position in the stream.
252 Return NULL if error.
256 AmlStreamGetCurrPos (
257 IN CONST AML_STREAM
* Stream
260 if (!IS_STREAM (Stream
)) {
265 if (IS_STREAM_FORWARD (Stream
)) {
266 return Stream
->Buffer
+ Stream
->Index
;
267 } else if (IS_STREAM_BACKWARD (Stream
)) {
268 return Stream
->Buffer
+ (Stream
->MaxBufferSize
- 1) - Stream
->Index
;
275 /** Get the space available in the stream.
277 @param [in] Stream Pointer to a stream.
279 @return Remaining space available in the stream.
280 Zero in case of error or if the stream is at its end.
284 AmlStreamGetFreeSpace (
285 IN CONST AML_STREAM
* Stream
288 if (!IS_STREAM (Stream
)) {
293 if (Stream
->Index
> Stream
->MaxBufferSize
) {
298 return Stream
->MaxBufferSize
- Stream
->Index
;
301 /** Move Stream by Offset bytes.
303 The stream current position is moved according to the stream direction
306 @param [in] Stream Pointer to a stream.
307 The stream must not be at its end.
308 @param [in] Offset Offset to move the stream of.
310 @retval EFI_SUCCESS The function completed successfully.
311 @retval EFI_INVALID_PARAMETER Invalid parameter.
312 @retval EFI_BUFFER_TOO_SMALL No space left in the buffer.
317 IN AML_STREAM
* Stream
,
321 if (!IS_STREAM (Stream
) ||
322 IS_END_OF_STREAM (Stream
) ||
325 return EFI_INVALID_PARAMETER
;
328 if (AmlStreamGetFreeSpace (Stream
) < Offset
) {
330 return EFI_BUFFER_TOO_SMALL
;
333 Stream
->Index
+= Offset
;
338 /** Rewind Stream of Offset bytes.
340 The stream current position is rewound according to the stream direction
341 (forward, backward). A stream going forward will be rewound backward.
343 @param [in] Stream Pointer to a stream.
344 @param [in] Offset Offset to rewind the stream of.
346 @retval EFI_SUCCESS The function completed successfully.
347 @retval EFI_INVALID_PARAMETER Invalid parameter.
348 @retval EFI_BUFFER_TOO_SMALL No space left in the buffer.
353 IN AML_STREAM
* Stream
,
357 if (!IS_STREAM (Stream
) ||
360 return EFI_INVALID_PARAMETER
;
363 if (AmlStreamGetIndex (Stream
) < Offset
) {
365 return EFI_BUFFER_TOO_SMALL
;
368 Stream
->Index
-= Offset
;
373 /** Reset the Stream (move the current position to the initial position).
375 @param [in] Stream Pointer to a stream.
377 @retval EFI_SUCCESS The function completed successfully.
378 @retval EFI_INVALID_PARAMETER Invalid parameter.
383 IN AML_STREAM
* Stream
386 if (!IS_STREAM (Stream
)) {
388 return EFI_INVALID_PARAMETER
;
396 /** Peek one byte at Stream's current position.
398 Stream's position is not moved when peeking.
400 @param [in] Stream Pointer to a stream.
401 The stream must not be at its end.
402 @param [out] OutByte Pointer holding the byte value of
403 the stream current position.
405 @retval EFI_SUCCESS The function completed successfully.
406 @retval EFI_INVALID_PARAMETER Invalid parameter.
407 @retval EFI_BUFFER_TOO_SMALL No space left in the buffer.
412 IN AML_STREAM
* Stream
,
418 if (!IS_STREAM (Stream
) ||
419 IS_END_OF_STREAM (Stream
) ||
422 return EFI_INVALID_PARAMETER
;
425 CurPos
= AmlStreamGetCurrPos (Stream
);
426 if (CurPos
== NULL
) {
428 return EFI_INVALID_PARAMETER
;
435 /** Read one byte at Stream's current position.
437 The stream current position is moved when reading.
439 @param [in] Stream Pointer to a stream.
440 The stream must not be at its end.
441 @param [out] OutByte Pointer holding the byte value of
442 the stream current position.
444 @retval EFI_SUCCESS The function completed successfully.
445 @retval EFI_INVALID_PARAMETER Invalid parameter.
446 @retval EFI_BUFFER_TOO_SMALL No space left in the buffer.
451 IN AML_STREAM
* Stream
,
457 if (!IS_STREAM (Stream
) ||
458 IS_END_OF_STREAM (Stream
) ||
461 return EFI_INVALID_PARAMETER
;
464 // Stream is checked in the function call.
465 Status
= AmlStreamPeekByte (Stream
, OutByte
);
466 if (EFI_ERROR (Status
)) {
471 Status
= AmlStreamProgress (Stream
, 1);
472 ASSERT_EFI_ERROR (Status
);
476 /** Write Size bytes in the stream.
478 If the stream goes backward (toward lower addresses), the bytes written
479 to the stream are not reverted.
480 In the example below, writing "Hello" to the stream will not revert
481 the string. The end of the stream buffer will contain "Hello world!".
483 +---------------+-----+-----+-----+-----+-----+-----+---- +------+
484 | ..... | ' ' | 'w' | 'o' | 'r' | 'l' | 'd' | '!' | '\0' |
485 +---------------+-----+-----+-----+-----+-----+-----+---- +------+
489 @param [in] Stream Pointer to a stream.
490 The stream must not be at its end.
491 @param [in] Buffer Pointer to the data to write.
492 @param [in] Size Number of bytes to write.
494 @retval EFI_SUCCESS The function completed successfully.
495 @retval EFI_INVALID_PARAMETER Invalid parameter.
496 @retval EFI_BUFFER_TOO_SMALL No space left in the buffer.
501 IN AML_STREAM
* Stream
,
502 IN CONST UINT8
* Buffer
,
508 if (!IS_STREAM (Stream
) ||
509 IS_END_OF_STREAM (Stream
) ||
513 return EFI_INVALID_PARAMETER
;
516 if (AmlStreamGetFreeSpace (Stream
) < Size
) {
518 return EFI_BUFFER_TOO_SMALL
;
521 CurrPos
= AmlStreamGetCurrPos (Stream
);
523 // If the Stream goes backward, prepare some space to copy the data.
524 if (IS_STREAM_BACKWARD (Stream
)) {
528 CopyMem (CurrPos
, Buffer
, Size
);
529 Stream
->Index
+= Size
;
534 /** Compare Size bytes between Stream1 and Stream2 from their
535 respective current position.
537 Stream1 and Stream2 must go in the same direction.
538 Stream1 and Stream2 are left unchanged.
540 @param [in] Stream1 First stream to compare.
541 The stream must not be at its end.
542 @param [in] Stream2 Second stream to compare.
543 The stream must not be at its end.
544 @param [in] Size Number of bytes to compare.
545 Must be lower than the minimum remaining space of
549 @retval TRUE If Stream1 and Stream2 have Size bytes equal,
550 from their respective current position.
551 The function completed successfully.
552 @retval FALSE Otherwise.
557 IN CONST AML_STREAM
* Stream1
,
558 IN CONST AML_STREAM
* Stream2
,
563 UINT8
* CurrPosStream1
;
564 UINT8
* CurrPosStream2
;
566 if (!IS_STREAM (Stream1
) ||
567 IS_END_OF_STREAM (Stream1
) ||
568 !IS_STREAM (Stream2
) ||
569 IS_END_OF_STREAM (Stream2
) ||
570 (Stream1
->Direction
!= Stream2
->Direction
) ||
576 // Check the Size is not longer than the remaining size of
577 // Stream1 and Stream2.
579 AmlStreamGetFreeSpace (Stream1
),
580 AmlStreamGetFreeSpace (Stream2
)
582 if (MinSize
< Size
) {
587 CurrPosStream1
= AmlStreamGetCurrPos (Stream1
);
588 if (CurrPosStream1
== NULL
) {
592 CurrPosStream2
= AmlStreamGetCurrPos (Stream2
);
593 if (CurrPosStream2
== NULL
) {
598 if (Stream1
->Direction
== EAmlStreamDirectionForward
) {
599 return (0 == CompareMem (CurrPosStream1
, CurrPosStream2
, MinSize
));
602 // The stream is already pointing on the last byte, thus the (-1).
603 // +---------------------+
604 // BStream | | | | | | | |M|E|T|0|
605 // +---------------------+
608 return (0 == CompareMem (
609 CurrPosStream1
- (MinSize
- 1),
610 CurrPosStream2
- (MinSize
- 1),
615 /** Copy Size bytes of the stream's data to DstBuffer.
617 For a backward stream, the bytes are copied starting from the
618 current stream position.
620 @param [out] DstBuffer Destination Buffer to copy the data to.
621 @param [in] MaxDstBufferSize Maximum size of DstBuffer.
623 @param [in] Stream Pointer to the stream to copy the data from.
624 @param [in] Size Number of bytes to copy from the stream
626 Must be lower than MaxDstBufferSize.
627 Must be lower than Stream's MaxBufferSize.
628 Return success if zero.
630 @retval EFI_SUCCESS The function completed successfully.
631 @retval EFI_INVALID_PARAMETER Invalid parameter.
636 OUT CHAR8
* DstBuffer
,
637 IN UINT32 MaxDstBufferSize
,
638 IN AML_STREAM
* Stream
,
642 CHAR8
* StreamBufferStart
;
644 // Stream is checked in the function call.
645 if ((DstBuffer
== NULL
) ||
646 (MaxDstBufferSize
== 0) ||
647 (Size
> MaxDstBufferSize
) ||
648 (Size
> AmlStreamGetMaxBufferSize (Stream
))) {
650 return EFI_INVALID_PARAMETER
;
657 // Find the address at which the data is starting.
658 StreamBufferStart
= (CHAR8
*)(IS_STREAM_FORWARD (Stream
) ?
660 AmlStreamGetCurrPos (Stream
));
662 CopyMem (DstBuffer
, StreamBufferStart
, Size
);