]> git.proxmox.com Git - mirror_edk2.git/blob - DynamicTablesPkg/Library/Common/AmlLib/Stream/AmlStream.c
419e796e50cbe29e62234916c6e39c2c625a2951
[mirror_edk2.git] / DynamicTablesPkg / Library / Common / AmlLib / Stream / AmlStream.c
1 /** @file
2 AML Stream.
3
4 Copyright (c) 2019 - 2020, Arm Limited. All rights reserved.<BR>
5
6 SPDX-License-Identifier: BSD-2-Clause-Patent
7 **/
8
9 #include <Stream/AmlStream.h>
10
11 /** Initialize a stream.
12
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
18 (forward, backward).
19
20 @retval EFI_SUCCESS The function completed successfully.
21 @retval EFI_INVALID_PARAMETER Invalid parameter.
22 **/
23 EFI_STATUS
24 EFIAPI
25 AmlStreamInit (
26 IN OUT AML_STREAM * Stream,
27 IN UINT8 * Buffer,
28 IN UINT32 MaxBufferSize,
29 IN EAML_STREAM_DIRECTION Direction
30 )
31 {
32 if ((Stream == NULL) ||
33 (Buffer == NULL) ||
34 (MaxBufferSize == 0) ||
35 ((Direction != EAmlStreamDirectionForward) &&
36 (Direction != EAmlStreamDirectionBackward))) {
37 ASSERT (0);
38 return EFI_INVALID_PARAMETER;
39 }
40
41 Stream->Buffer = Buffer;
42 Stream->MaxBufferSize = MaxBufferSize;
43 Stream->Index = 0;
44 Stream->Direction = Direction;
45
46 return EFI_SUCCESS;
47 }
48
49 /** Clone a stream.
50
51 Cloning a stream means copying all the values of the input Stream
52 in the ClonedStream.
53
54 @param [in] Stream Pointer to the stream to clone.
55 @param [in] ClonedStream Pointer to the stream to initialize.
56
57 @retval EFI_SUCCESS The function completed successfully.
58 @retval EFI_INVALID_PARAMETER Invalid parameter.
59 **/
60 EFI_STATUS
61 EFIAPI
62 AmlStreamClone (
63 IN CONST AML_STREAM * Stream,
64 OUT AML_STREAM * ClonedStream
65 )
66 {
67 if (!IS_STREAM (Stream) ||
68 (ClonedStream == NULL)) {
69 ASSERT (0);
70 return EFI_INVALID_PARAMETER;
71 }
72
73 ClonedStream->Buffer = Stream->Buffer;
74 ClonedStream->MaxBufferSize = Stream->MaxBufferSize;
75 ClonedStream->Index = Stream->Index;
76 ClonedStream->Direction = Stream->Direction;
77
78 return EFI_SUCCESS;
79 }
80
81 /** Initialize a sub-stream from a stream.
82
83 A sub-stream is a stream initialized at the current position of the input
84 stream:
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;
89
90 E.g.: For a forward stream:
91 +----------------+----------------+
92 |ABCD.........XYZ| Free Space |
93 +----------------+----------------+
94 ^ ^ ^
95 Stream: Buffer CurrPos EndOfBuff
96 Sub-stream: Buffer/CurrPos EndOfBuff
97
98 @param [in] Stream Pointer to the stream from which a sub-stream is
99 created.
100 @param [in] SubStream Pointer to the stream to initialize.
101
102 @retval EFI_SUCCESS The function completed successfully.
103 @retval EFI_INVALID_PARAMETER Invalid parameter.
104 **/
105 EFI_STATUS
106 EFIAPI
107 AmlStreamInitSubStream (
108 IN CONST AML_STREAM * Stream,
109 OUT AML_STREAM * SubStream
110 )
111 {
112 if (!IS_STREAM (Stream) ||
113 (SubStream == NULL)) {
114 ASSERT (0);
115 return EFI_INVALID_PARAMETER;
116 }
117
118 if (IS_STREAM_FORWARD (Stream)) {
119 SubStream->Buffer = AmlStreamGetCurrPos (Stream);
120 } else if (IS_STREAM_BACKWARD (Stream)) {
121 SubStream->Buffer = Stream->Buffer;
122 } else {
123 ASSERT (0);
124 return EFI_INVALID_PARAMETER;
125 }
126
127 SubStream->MaxBufferSize = AmlStreamGetFreeSpace (Stream);
128 SubStream->Index = 0;
129 SubStream->Direction = Stream->Direction;
130
131 return EFI_SUCCESS;
132 }
133
134 /** Get the buffer of a stream.
135
136 @param [in] Stream Pointer to a stream.
137
138 @return The stream's Buffer.
139 NULL otherwise.
140 **/
141 UINT8 *
142 EFIAPI
143 AmlStreamGetBuffer (
144 IN CONST AML_STREAM * Stream
145 )
146 {
147 if (!IS_STREAM (Stream)) {
148 ASSERT (0);
149 return NULL;
150 }
151 return Stream->Buffer;
152 }
153
154 /** Get the size of Stream's Buffer.
155
156 @param [in] Stream Pointer to a stream.
157
158 @return The Size of Stream's Buffer.
159 Return 0 if Stream is invalid.
160 **/
161 UINT32
162 EFIAPI
163 AmlStreamGetMaxBufferSize (
164 IN CONST AML_STREAM * Stream
165 )
166 {
167 if (!IS_STREAM (Stream)) {
168 ASSERT (0);
169 return 0;
170 }
171 return Stream->MaxBufferSize;
172 }
173
174 /** Reduce the maximal size of Stream's Buffer (MaxBufferSize field).
175
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.
179
180 @retval EFI_SUCCESS The function completed successfully.
181 @retval EFI_INVALID_PARAMETER Invalid parameter.
182 **/
183 EFI_STATUS
184 EFIAPI
185 AmlStreamReduceMaxBufferSize (
186 IN AML_STREAM * Stream,
187 IN UINT32 Diff
188 )
189 {
190 if (!IS_STREAM (Stream) ||
191 (Diff == 0) ||
192 ((Stream->MaxBufferSize - Diff) <= Stream->Index)) {
193 ASSERT (0);
194 return EFI_INVALID_PARAMETER;
195 }
196
197 Stream->MaxBufferSize -= Diff;
198 return EFI_SUCCESS;
199 }
200
201 /** Get Stream's Index.
202
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.
208
209 @param [in] Stream Pointer to a stream.
210
211 @return Stream's Index.
212 Return 0 if Stream is invalid.
213 **/
214 UINT32
215 EFIAPI
216 AmlStreamGetIndex (
217 IN CONST AML_STREAM * Stream
218 )
219 {
220 if (!IS_STREAM (Stream)) {
221 ASSERT (0);
222 return 0;
223 }
224 return Stream->Index;
225 }
226
227 /** Get Stream's Direction.
228
229 @param [in] Stream Pointer to a stream.
230
231 @return Stream's Direction.
232 Return EAmlStreamDirectionUnknown if Stream is invalid.
233 **/
234 EAML_STREAM_DIRECTION
235 EFIAPI
236 AmlStreamGetDirection (
237 IN CONST AML_STREAM * Stream
238 )
239 {
240 if (!IS_STREAM (Stream)) {
241 ASSERT (0);
242 return EAmlStreamDirectionInvalid;
243 }
244 return Stream->Direction;
245 }
246
247 /** Return a pointer to the current position in the stream.
248
249 @param [in] Stream Pointer to a stream.
250
251 @return The current position in the stream.
252 Return NULL if error.
253 **/
254 UINT8 *
255 EFIAPI
256 AmlStreamGetCurrPos (
257 IN CONST AML_STREAM * Stream
258 )
259 {
260 if (!IS_STREAM (Stream)) {
261 ASSERT (0);
262 return NULL;
263 }
264
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;
269 } else {
270 ASSERT (0);
271 return NULL;
272 }
273 }
274
275 /** Get the space available in the stream.
276
277 @param [in] Stream Pointer to a stream.
278
279 @return Remaining space available in the stream.
280 Zero in case of error or if the stream is at its end.
281 **/
282 UINT32
283 EFIAPI
284 AmlStreamGetFreeSpace (
285 IN CONST AML_STREAM * Stream
286 )
287 {
288 if (!IS_STREAM (Stream)) {
289 ASSERT (0);
290 return 0;
291 }
292
293 if (Stream->Index > Stream->MaxBufferSize) {
294 ASSERT (0);
295 return 0;
296 }
297
298 return Stream->MaxBufferSize - Stream->Index;
299 }
300
301 /** Move Stream by Offset bytes.
302
303 The stream current position is moved according to the stream direction
304 (forward, backward).
305
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.
309
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.
313 **/
314 EFI_STATUS
315 EFIAPI
316 AmlStreamProgress (
317 IN AML_STREAM * Stream,
318 IN UINT32 Offset
319 )
320 {
321 if (!IS_STREAM (Stream) ||
322 IS_END_OF_STREAM (Stream) ||
323 (Offset == 0)) {
324 ASSERT (0);
325 return EFI_INVALID_PARAMETER;
326 }
327
328 if (AmlStreamGetFreeSpace (Stream) < Offset) {
329 ASSERT (0);
330 return EFI_BUFFER_TOO_SMALL;
331 }
332
333 Stream->Index += Offset;
334
335 return EFI_SUCCESS;
336 }
337
338 /** Rewind Stream of Offset bytes.
339
340 The stream current position is rewound according to the stream direction
341 (forward, backward). A stream going forward will be rewound backward.
342
343 @param [in] Stream Pointer to a stream.
344 @param [in] Offset Offset to rewind the stream of.
345
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.
349 **/
350 EFI_STATUS
351 EFIAPI
352 AmlStreamRewind (
353 IN AML_STREAM * Stream,
354 IN UINT32 Offset
355 )
356 {
357 if (!IS_STREAM (Stream) ||
358 (Offset == 0)) {
359 ASSERT (0);
360 return EFI_INVALID_PARAMETER;
361 }
362
363 if (AmlStreamGetIndex (Stream) < Offset) {
364 ASSERT (0);
365 return EFI_BUFFER_TOO_SMALL;
366 }
367
368 Stream->Index -= Offset;
369
370 return EFI_SUCCESS;
371 }
372
373 /** Reset the Stream (move the current position to the initial position).
374
375 @param [in] Stream Pointer to a stream.
376
377 @retval EFI_SUCCESS The function completed successfully.
378 @retval EFI_INVALID_PARAMETER Invalid parameter.
379 **/
380 EFI_STATUS
381 EFIAPI
382 AmlStreamReset (
383 IN AML_STREAM * Stream
384 )
385 {
386 if (!IS_STREAM (Stream)) {
387 ASSERT (0);
388 return EFI_INVALID_PARAMETER;
389 }
390
391 Stream->Index = 0;
392
393 return EFI_SUCCESS;
394 }
395
396 /** Peek one byte at Stream's current position.
397
398 Stream's position is not moved when peeking.
399
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.
404
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.
408 **/
409 EFI_STATUS
410 EFIAPI
411 AmlStreamPeekByte (
412 IN AML_STREAM * Stream,
413 OUT UINT8 * OutByte
414 )
415 {
416 UINT8 * CurPos;
417
418 if (!IS_STREAM (Stream) ||
419 IS_END_OF_STREAM (Stream) ||
420 (OutByte == NULL)) {
421 ASSERT (0);
422 return EFI_INVALID_PARAMETER;
423 }
424
425 CurPos = AmlStreamGetCurrPos (Stream);
426 if (CurPos == NULL) {
427 ASSERT (0);
428 return EFI_INVALID_PARAMETER;
429 }
430
431 *OutByte = *CurPos;
432 return EFI_SUCCESS;
433 }
434
435 /** Read one byte at Stream's current position.
436
437 The stream current position is moved when reading.
438
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.
443
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.
447 **/
448 EFI_STATUS
449 EFIAPI
450 AmlStreamReadByte (
451 IN AML_STREAM * Stream,
452 OUT UINT8 * OutByte
453 )
454 {
455 EFI_STATUS Status;
456
457 if (!IS_STREAM (Stream) ||
458 IS_END_OF_STREAM (Stream) ||
459 (OutByte == NULL)) {
460 ASSERT (0);
461 return EFI_INVALID_PARAMETER;
462 }
463
464 // Stream is checked in the function call.
465 Status = AmlStreamPeekByte (Stream, OutByte);
466 if (EFI_ERROR (Status)) {
467 ASSERT (0);
468 return Status;
469 }
470
471 Status = AmlStreamProgress (Stream, 1);
472 ASSERT_EFI_ERROR (Status);
473 return Status;
474 }
475
476 /** Write Size bytes in the stream.
477
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!".
482 Stream buffer:
483 +---------------+-----+-----+-----+-----+-----+-----+---- +------+
484 | ..... | ' ' | 'w' | 'o' | 'r' | 'l' | 'd' | '!' | '\0' |
485 +---------------+-----+-----+-----+-----+-----+-----+---- +------+
486 ^
487 Current position.
488
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.
493
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.
497 **/
498 EFI_STATUS
499 EFIAPI
500 AmlStreamWrite (
501 IN AML_STREAM * Stream,
502 IN CONST UINT8 * Buffer,
503 IN UINT32 Size
504 )
505 {
506 UINT8 * CurrPos;
507
508 if (!IS_STREAM (Stream) ||
509 IS_END_OF_STREAM (Stream) ||
510 (Buffer == NULL) ||
511 (Size == 0)) {
512 ASSERT (0);
513 return EFI_INVALID_PARAMETER;
514 }
515
516 if (AmlStreamGetFreeSpace (Stream) < Size) {
517 ASSERT (0);
518 return EFI_BUFFER_TOO_SMALL;
519 }
520
521 CurrPos = AmlStreamGetCurrPos (Stream);
522
523 // If the Stream goes backward, prepare some space to copy the data.
524 if (IS_STREAM_BACKWARD (Stream)) {
525 CurrPos -= Size;
526 }
527
528 CopyMem (CurrPos, Buffer, Size);
529 Stream->Index += Size;
530
531 return EFI_SUCCESS;
532 }
533
534 /** Compare Size bytes between Stream1 and Stream2 from their
535 respective current position.
536
537 Stream1 and Stream2 must go in the same direction.
538 Stream1 and Stream2 are left unchanged.
539
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
546 Stream1 and Stream2.
547 Must be non-zero.
548
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.
553 **/
554 BOOLEAN
555 EFIAPI
556 AmlStreamCmp (
557 IN CONST AML_STREAM * Stream1,
558 IN CONST AML_STREAM * Stream2,
559 IN UINT32 Size
560 )
561 {
562 UINT32 MinSize;
563 UINT8 * CurrPosStream1;
564 UINT8 * CurrPosStream2;
565
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) ||
571 (Size == 0)) {
572 ASSERT (0);
573 return FALSE;
574 }
575
576 // Check the Size is not longer than the remaining size of
577 // Stream1 and Stream2.
578 MinSize = MIN (
579 AmlStreamGetFreeSpace (Stream1),
580 AmlStreamGetFreeSpace (Stream2)
581 );
582 if (MinSize < Size) {
583 ASSERT (0);
584 return FALSE;
585 }
586
587 CurrPosStream1 = AmlStreamGetCurrPos (Stream1);
588 if (CurrPosStream1 == NULL) {
589 ASSERT (0);
590 return FALSE;
591 }
592 CurrPosStream2 = AmlStreamGetCurrPos (Stream2);
593 if (CurrPosStream2 == NULL) {
594 ASSERT (0);
595 return FALSE;
596 }
597
598 if (Stream1->Direction == EAmlStreamDirectionForward) {
599 return (0 == CompareMem (CurrPosStream1, CurrPosStream2, MinSize));
600 }
601
602 // The stream is already pointing on the last byte, thus the (-1).
603 // +---------------------+
604 // BStream | | | | | | | |M|E|T|0|
605 // +---------------------+
606 // ^
607 // CurrPos
608 return (0 == CompareMem (
609 CurrPosStream1 - (MinSize - 1),
610 CurrPosStream2 - (MinSize - 1),
611 MinSize
612 ));
613 }
614
615 /** Copy Size bytes of the stream's data to DstBuffer.
616
617 For a backward stream, the bytes are copied starting from the
618 current stream position.
619
620 @param [out] DstBuffer Destination Buffer to copy the data to.
621 @param [in] MaxDstBufferSize Maximum size of DstBuffer.
622 Must be non-zero.
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
625 buffer.
626 Must be lower than MaxDstBufferSize.
627 Must be lower than Stream's MaxBufferSize.
628 Return success if zero.
629
630 @retval EFI_SUCCESS The function completed successfully.
631 @retval EFI_INVALID_PARAMETER Invalid parameter.
632 **/
633 EFI_STATUS
634 EFIAPI
635 AmlStreamCpyS (
636 OUT CHAR8 * DstBuffer,
637 IN UINT32 MaxDstBufferSize,
638 IN AML_STREAM * Stream,
639 IN UINT32 Size
640 )
641 {
642 CHAR8 * StreamBufferStart;
643
644 // Stream is checked in the function call.
645 if ((DstBuffer == NULL) ||
646 (MaxDstBufferSize == 0) ||
647 (Size > MaxDstBufferSize) ||
648 (Size > AmlStreamGetMaxBufferSize (Stream))) {
649 ASSERT (0);
650 return EFI_INVALID_PARAMETER;
651 }
652
653 if (Size == 0) {
654 return EFI_SUCCESS;
655 }
656
657 // Find the address at which the data is starting.
658 StreamBufferStart = (CHAR8*)(IS_STREAM_FORWARD (Stream) ?
659 Stream->Buffer :
660 AmlStreamGetCurrPos (Stream));
661
662 CopyMem (DstBuffer, StreamBufferStart, Size);
663
664 return EFI_SUCCESS;
665 }