1 | /** @file
|
---|
2 | Implementation of the InternalMemCopyMem routine. This function is broken
|
---|
3 | out into its own source file so that it can be excluded from a build for a
|
---|
4 | particular platform easily if an optimized version is desired.
|
---|
5 |
|
---|
6 | Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>
|
---|
7 | Copyright (c) 2012 - 2013, ARM Ltd. All rights reserved.<BR>
|
---|
8 | Copyright (c) 2016, Linaro Ltd. All rights reserved.<BR>
|
---|
9 |
|
---|
10 | SPDX-License-Identifier: BSD-2-Clause-Patent
|
---|
11 |
|
---|
12 | **/
|
---|
13 |
|
---|
14 | #include "MemLibInternals.h"
|
---|
15 |
|
---|
16 | /**
|
---|
17 | Copy Length bytes from Source to Destination.
|
---|
18 |
|
---|
19 | @param DestinationBuffer The target of the copy request.
|
---|
20 | @param SourceBuffer The place to copy from.
|
---|
21 | @param Length The number of bytes to copy.
|
---|
22 |
|
---|
23 | @return Destination
|
---|
24 |
|
---|
25 | **/
|
---|
26 | VOID *
|
---|
27 | EFIAPI
|
---|
28 | InternalMemCopyMem (
|
---|
29 | OUT VOID *DestinationBuffer,
|
---|
30 | IN CONST VOID *SourceBuffer,
|
---|
31 | IN UINTN Length
|
---|
32 | )
|
---|
33 | {
|
---|
34 | //
|
---|
35 | // Declare the local variables that actually move the data elements as
|
---|
36 | // volatile to prevent the optimizer from replacing this function with
|
---|
37 | // the intrinsic memcpy()
|
---|
38 | //
|
---|
39 | volatile UINT8 *Destination8;
|
---|
40 | CONST UINT8 *Source8;
|
---|
41 | volatile UINT32 *Destination32;
|
---|
42 | CONST UINT32 *Source32;
|
---|
43 | volatile UINT64 *Destination64;
|
---|
44 | CONST UINT64 *Source64;
|
---|
45 | UINTN Alignment;
|
---|
46 |
|
---|
47 | if ((((UINTN)DestinationBuffer & 0x7) == 0) && (((UINTN)SourceBuffer & 0x7) == 0) && (Length >= 8)) {
|
---|
48 | if (SourceBuffer > DestinationBuffer) {
|
---|
49 | Destination64 = (UINT64 *)DestinationBuffer;
|
---|
50 | Source64 = (CONST UINT64 *)SourceBuffer;
|
---|
51 | while (Length >= 8) {
|
---|
52 | *(Destination64++) = *(Source64++);
|
---|
53 | Length -= 8;
|
---|
54 | }
|
---|
55 |
|
---|
56 | // Finish if there are still some bytes to copy
|
---|
57 | Destination8 = (UINT8 *)Destination64;
|
---|
58 | Source8 = (CONST UINT8 *)Source64;
|
---|
59 | while (Length-- != 0) {
|
---|
60 | *(Destination8++) = *(Source8++);
|
---|
61 | }
|
---|
62 | } else if (SourceBuffer < DestinationBuffer) {
|
---|
63 | Destination64 = (UINT64 *)((UINTN)DestinationBuffer + Length);
|
---|
64 | Source64 = (CONST UINT64 *)((UINTN)SourceBuffer + Length);
|
---|
65 |
|
---|
66 | // Destination64 and Source64 were aligned on a 64-bit boundary
|
---|
67 | // but if length is not a multiple of 8 bytes then they won't be
|
---|
68 | // anymore.
|
---|
69 |
|
---|
70 | Alignment = Length & 0x7;
|
---|
71 | if (Alignment != 0) {
|
---|
72 | Destination8 = (UINT8 *)Destination64;
|
---|
73 | Source8 = (CONST UINT8 *)Source64;
|
---|
74 |
|
---|
75 | while (Alignment-- != 0) {
|
---|
76 | *(--Destination8) = *(--Source8);
|
---|
77 | --Length;
|
---|
78 | }
|
---|
79 |
|
---|
80 | Destination64 = (UINT64 *)Destination8;
|
---|
81 | Source64 = (CONST UINT64 *)Source8;
|
---|
82 | }
|
---|
83 |
|
---|
84 | while (Length > 0) {
|
---|
85 | *(--Destination64) = *(--Source64);
|
---|
86 | Length -= 8;
|
---|
87 | }
|
---|
88 | }
|
---|
89 | } else if ((((UINTN)DestinationBuffer & 0x3) == 0) && (((UINTN)SourceBuffer & 0x3) == 0) && (Length >= 4)) {
|
---|
90 | if (SourceBuffer > DestinationBuffer) {
|
---|
91 | Destination32 = (UINT32 *)DestinationBuffer;
|
---|
92 | Source32 = (CONST UINT32 *)SourceBuffer;
|
---|
93 | while (Length >= 4) {
|
---|
94 | *(Destination32++) = *(Source32++);
|
---|
95 | Length -= 4;
|
---|
96 | }
|
---|
97 |
|
---|
98 | // Finish if there are still some bytes to copy
|
---|
99 | Destination8 = (UINT8 *)Destination32;
|
---|
100 | Source8 = (CONST UINT8 *)Source32;
|
---|
101 | while (Length-- != 0) {
|
---|
102 | *(Destination8++) = *(Source8++);
|
---|
103 | }
|
---|
104 | } else if (SourceBuffer < DestinationBuffer) {
|
---|
105 | Destination32 = (UINT32 *)((UINTN)DestinationBuffer + Length);
|
---|
106 | Source32 = (CONST UINT32 *)((UINTN)SourceBuffer + Length);
|
---|
107 |
|
---|
108 | // Destination32 and Source32 were aligned on a 32-bit boundary
|
---|
109 | // but if length is not a multiple of 4 bytes then they won't be
|
---|
110 | // anymore.
|
---|
111 |
|
---|
112 | Alignment = Length & 0x3;
|
---|
113 | if (Alignment != 0) {
|
---|
114 | Destination8 = (UINT8 *)Destination32;
|
---|
115 | Source8 = (CONST UINT8 *)Source32;
|
---|
116 |
|
---|
117 | while (Alignment-- != 0) {
|
---|
118 | *(--Destination8) = *(--Source8);
|
---|
119 | --Length;
|
---|
120 | }
|
---|
121 |
|
---|
122 | Destination32 = (UINT32 *)Destination8;
|
---|
123 | Source32 = (CONST UINT32 *)Source8;
|
---|
124 | }
|
---|
125 |
|
---|
126 | while (Length > 0) {
|
---|
127 | *(--Destination32) = *(--Source32);
|
---|
128 | Length -= 4;
|
---|
129 | }
|
---|
130 | }
|
---|
131 | } else {
|
---|
132 | if (SourceBuffer > DestinationBuffer) {
|
---|
133 | Destination8 = (UINT8 *)DestinationBuffer;
|
---|
134 | Source8 = (CONST UINT8 *)SourceBuffer;
|
---|
135 | while (Length-- != 0) {
|
---|
136 | *(Destination8++) = *(Source8++);
|
---|
137 | }
|
---|
138 | } else if (SourceBuffer < DestinationBuffer) {
|
---|
139 | Destination8 = (UINT8 *)DestinationBuffer + (Length - 1);
|
---|
140 | Source8 = (CONST UINT8 *)SourceBuffer + (Length - 1);
|
---|
141 | while (Length-- != 0) {
|
---|
142 | *(Destination8--) = *(Source8--);
|
---|
143 | }
|
---|
144 | }
|
---|
145 | }
|
---|
146 |
|
---|
147 | return DestinationBuffer;
|
---|
148 | }
|
---|