1314879Simp/** @file
2314879Simp  Provides services to allocate and free memory buffers of various memory types and alignments.
3314879Simp
4314879Simp  The Memory Allocation Library abstracts various common memory allocation operations. This library
5314879Simp  allows code to be written in a phase-independent manner because the allocation of memory in PEI, DXE,
6314879Simp  and SMM (for example) is done via a different mechanism. Using a common library interface makes it
7314879Simp  much easier to port algorithms from phase to phase.
8314879Simp
9314879SimpCopyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>
10314879SimpThis program and the accompanying materials
11314879Simpare licensed and made available under the terms and conditions of the BSD License
12314879Simpwhich accompanies this distribution.  The full text of the license may be found at
13314879Simphttp://opensource.org/licenses/bsd-license.php
14314879Simp
15314879SimpTHE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
16314879SimpWITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
17314879Simp
18314879Simp**/
19314879Simp
20314879Simp#ifndef __MEMORY_ALLOCATION_LIB_H__
21314879Simp#define __MEMORY_ALLOCATION_LIB_H__
22314879Simp
23314879Simp/**
24314879Simp  Allocates one or more 4KB pages of type EfiBootServicesData.
25314879Simp
26314879Simp  Allocates the number of 4KB pages of type EfiBootServicesData and returns a pointer to the
27314879Simp  allocated buffer.  The buffer returned is aligned on a 4KB boundary.  If Pages is 0, then NULL
28314879Simp  is returned.  If there is not enough memory remaining to satisfy the request, then NULL is
29314879Simp  returned.
30314879Simp
31314879Simp  @param  Pages                 The number of 4 KB pages to allocate.
32314879Simp
33314879Simp  @return A pointer to the allocated buffer or NULL if allocation fails.
34314879Simp
35314879Simp**/
36314879SimpVOID *
37314879SimpEFIAPI
38314879SimpAllocatePages (
39314879Simp  IN UINTN  Pages
40314879Simp  );
41314879Simp
42314879Simp/**
43314879Simp  Allocates one or more 4KB pages of type EfiRuntimeServicesData.
44314879Simp
45314879Simp  Allocates the number of 4KB pages of type EfiRuntimeServicesData and returns a pointer to the
46314879Simp  allocated buffer.  The buffer returned is aligned on a 4KB boundary.  If Pages is 0, then NULL
47314879Simp  is returned.  If there is not enough memory remaining to satisfy the request, then NULL is
48314879Simp  returned.
49314879Simp
50314879Simp  @param  Pages                 The number of 4 KB pages to allocate.
51314879Simp
52314879Simp  @return A pointer to the allocated buffer or NULL if allocation fails.
53314879Simp
54314879Simp**/
55314879SimpVOID *
56314879SimpEFIAPI
57314879SimpAllocateRuntimePages (
58314879Simp  IN UINTN  Pages
59314879Simp  );
60314879Simp
61314879Simp/**
62314879Simp  Allocates one or more 4KB pages of type EfiReservedMemoryType.
63314879Simp
64314879Simp  Allocates the number of 4KB pages of type EfiReservedMemoryType and returns a pointer to the
65314879Simp  allocated buffer.  The buffer returned is aligned on a 4KB boundary.  If Pages is 0, then NULL
66314879Simp  is returned.  If there is not enough memory remaining to satisfy the request, then NULL is
67314879Simp  returned.
68314879Simp
69314879Simp  @param  Pages                 The number of 4 KB pages to allocate.
70314879Simp
71314879Simp  @return A pointer to the allocated buffer or NULL if allocation fails.
72314879Simp
73314879Simp**/
74314879SimpVOID *
75314879SimpEFIAPI
76314879SimpAllocateReservedPages (
77314879Simp  IN UINTN  Pages
78314879Simp  );
79314879Simp
80314879Simp/**
81314879Simp  Frees one or more 4KB pages that were previously allocated with one of the page allocation
82314879Simp  functions in the Memory Allocation Library.
83314879Simp
84314879Simp  Frees the number of 4KB pages specified by Pages from the buffer specified by Buffer.  Buffer
85314879Simp  must have been allocated on a previous call to the page allocation services of the Memory
86314879Simp  Allocation Library.  If it is not possible to free allocated pages, then this function will
87314879Simp  perform no actions.
88314879Simp
89314879Simp  If Buffer was not allocated with a page allocation function in the Memory Allocation Library,
90314879Simp  then ASSERT().
91314879Simp  If Pages is zero, then ASSERT().
92314879Simp
93314879Simp  @param  Buffer                Pointer to the buffer of pages to free.
94314879Simp  @param  Pages                 The number of 4 KB pages to free.
95314879Simp
96314879Simp**/
97314879SimpVOID
98314879SimpEFIAPI
99314879SimpFreePages (
100314879Simp  IN VOID   *Buffer,
101314879Simp  IN UINTN  Pages
102314879Simp  );
103314879Simp
104314879Simp/**
105314879Simp  Allocates one or more 4KB pages of type EfiBootServicesData at a specified alignment.
106314879Simp
107314879Simp  Allocates the number of 4KB pages specified by Pages of type EfiBootServicesData with an
108314879Simp  alignment specified by Alignment.  The allocated buffer is returned.  If Pages is 0, then NULL is
109314879Simp  returned.  If there is not enough memory at the specified alignment remaining to satisfy the
110314879Simp  request, then NULL is returned.
111314879Simp
112314879Simp  If Alignment is not a power of two and Alignment is not zero, then ASSERT().
113314879Simp  If Pages plus EFI_SIZE_TO_PAGES (Alignment) overflows, then ASSERT().
114314879Simp
115314879Simp  @param  Pages                 The number of 4 KB pages to allocate.
116314879Simp  @param  Alignment             The requested alignment of the allocation.  Must be a power of two.
117314879Simp                                If Alignment is zero, then byte alignment is used.
118314879Simp
119314879Simp  @return A pointer to the allocated buffer or NULL if allocation fails.
120314879Simp
121314879Simp**/
122314879SimpVOID *
123314879SimpEFIAPI
124314879SimpAllocateAlignedPages (
125314879Simp  IN UINTN  Pages,
126314879Simp  IN UINTN  Alignment
127314879Simp  );
128314879Simp
129314879Simp/**
130314879Simp  Allocates one or more 4KB pages of type EfiRuntimeServicesData at a specified alignment.
131314879Simp
132314879Simp  Allocates the number of 4KB pages specified by Pages of type EfiRuntimeServicesData with an
133314879Simp  alignment specified by Alignment.  The allocated buffer is returned.  If Pages is 0, then NULL is
134314879Simp  returned.  If there is not enough memory at the specified alignment remaining to satisfy the
135314879Simp  request, then NULL is returned.
136314879Simp
137314879Simp  If Alignment is not a power of two and Alignment is not zero, then ASSERT().
138314879Simp  If Pages plus EFI_SIZE_TO_PAGES (Alignment) overflows, then ASSERT().
139314879Simp
140314879Simp  @param  Pages                 The number of 4 KB pages to allocate.
141314879Simp  @param  Alignment             The requested alignment of the allocation.  Must be a power of two.
142314879Simp                                If Alignment is zero, then byte alignment is used.
143314879Simp
144314879Simp  @return A pointer to the allocated buffer or NULL if allocation fails.
145314879Simp
146314879Simp**/
147314879SimpVOID *
148314879SimpEFIAPI
149314879SimpAllocateAlignedRuntimePages (
150314879Simp  IN UINTN  Pages,
151314879Simp  IN UINTN  Alignment
152314879Simp  );
153314879Simp
154314879Simp/**
155314879Simp  Allocates one or more 4KB pages of type EfiReservedMemoryType at a specified alignment.
156314879Simp
157314879Simp  Allocates the number of 4KB pages specified by Pages of type EfiReservedMemoryType with an
158314879Simp  alignment specified by Alignment.  The allocated buffer is returned.  If Pages is 0, then NULL is
159314879Simp  returned.  If there is not enough memory at the specified alignment remaining to satisfy the
160314879Simp  request, then NULL is returned.
161314879Simp
162314879Simp  If Alignment is not a power of two and Alignment is not zero, then ASSERT().
163314879Simp  If Pages plus EFI_SIZE_TO_PAGES (Alignment) overflows, then ASSERT().
164314879Simp
165314879Simp  @param  Pages                 The number of 4 KB pages to allocate.
166314879Simp  @param  Alignment             The requested alignment of the allocation.  Must be a power of two.
167314879Simp                                If Alignment is zero, then byte alignment is used.
168314879Simp
169314879Simp  @return A pointer to the allocated buffer or NULL if allocation fails.
170314879Simp
171314879Simp**/
172314879SimpVOID *
173314879SimpEFIAPI
174314879SimpAllocateAlignedReservedPages (
175314879Simp  IN UINTN  Pages,
176314879Simp  IN UINTN  Alignment
177314879Simp  );
178314879Simp
179314879Simp/**
180314879Simp  Frees one or more 4KB pages that were previously allocated with one of the aligned page
181314879Simp  allocation functions in the Memory Allocation Library.
182314879Simp
183314879Simp  Frees the number of 4KB pages specified by Pages from the buffer specified by Buffer.  Buffer
184314879Simp  must have been allocated on a previous call to the aligned page allocation services of the Memory
185314879Simp  Allocation Library.  If it is not possible to free allocated pages, then this function will
186314879Simp  perform no actions.
187314879Simp
188314879Simp  If Buffer was not allocated with an aligned page allocation function in the Memory Allocation
189314879Simp  Library, then ASSERT().
190314879Simp  If Pages is zero, then ASSERT().
191314879Simp
192314879Simp  @param  Buffer                Pointer to the buffer of pages to free.
193314879Simp  @param  Pages                 The number of 4 KB pages to free.
194314879Simp
195314879Simp**/
196314879SimpVOID
197314879SimpEFIAPI
198314879SimpFreeAlignedPages (
199314879Simp  IN VOID   *Buffer,
200314879Simp  IN UINTN  Pages
201314879Simp  );
202314879Simp
203314879Simp/**
204314879Simp  Allocates a buffer of type EfiBootServicesData.
205314879Simp
206314879Simp  Allocates the number bytes specified by AllocationSize of type EfiBootServicesData and returns a
207314879Simp  pointer to the allocated buffer.  If AllocationSize is 0, then a valid buffer of 0 size is
208314879Simp  returned.  If there is not enough memory remaining to satisfy the request, then NULL is returned.
209314879Simp
210314879Simp  @param  AllocationSize        The number of bytes to allocate.
211314879Simp
212314879Simp  @return A pointer to the allocated buffer or NULL if allocation fails.
213314879Simp
214314879Simp**/
215314879SimpVOID *
216314879SimpEFIAPI
217314879SimpAllocatePool (
218314879Simp  IN UINTN  AllocationSize
219314879Simp  );
220314879Simp
221314879Simp/**
222314879Simp  Allocates a buffer of type EfiRuntimeServicesData.
223314879Simp
224314879Simp  Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData and returns
225314879Simp  a pointer to the allocated buffer.  If AllocationSize is 0, then a valid buffer of 0 size is
226314879Simp  returned.  If there is not enough memory remaining to satisfy the request, then NULL is returned.
227314879Simp
228314879Simp  @param  AllocationSize        The number of bytes to allocate.
229314879Simp
230314879Simp  @return A pointer to the allocated buffer or NULL if allocation fails.
231314879Simp
232314879Simp**/
233314879SimpVOID *
234314879SimpEFIAPI
235314879SimpAllocateRuntimePool (
236314879Simp  IN UINTN  AllocationSize
237314879Simp  );
238314879Simp
239314879Simp/**
240314879Simp  Allocates a buffer of type EfiReservedMemoryType.
241314879Simp
242314879Simp  Allocates the number bytes specified by AllocationSize of type EfiReservedMemoryType and returns
243314879Simp  a pointer to the allocated buffer.  If AllocationSize is 0, then a valid buffer of 0 size is
244314879Simp  returned.  If there is not enough memory remaining to satisfy the request, then NULL is returned.
245314879Simp
246314879Simp  @param  AllocationSize        The number of bytes to allocate.
247314879Simp
248314879Simp  @return A pointer to the allocated buffer or NULL if allocation fails.
249314879Simp
250314879Simp**/
251314879SimpVOID *
252314879SimpEFIAPI
253314879SimpAllocateReservedPool (
254314879Simp  IN UINTN  AllocationSize
255314879Simp  );
256314879Simp
257314879Simp/**
258314879Simp  Allocates and zeros a buffer of type EfiBootServicesData.
259314879Simp
260314879Simp  Allocates the number bytes specified by AllocationSize of type EfiBootServicesData, clears the
261314879Simp  buffer with zeros, and returns a pointer to the allocated buffer.  If AllocationSize is 0, then a
262314879Simp  valid buffer of 0 size is returned.  If there is not enough memory remaining to satisfy the
263314879Simp  request, then NULL is returned.
264314879Simp
265314879Simp  @param  AllocationSize        The number of bytes to allocate and zero.
266314879Simp
267314879Simp  @return A pointer to the allocated buffer or NULL if allocation fails.
268314879Simp
269314879Simp**/
270314879SimpVOID *
271314879SimpEFIAPI
272314879SimpAllocateZeroPool (
273314879Simp  IN UINTN  AllocationSize
274314879Simp  );
275314879Simp
276314879Simp/**
277314879Simp  Allocates and zeros a buffer of type EfiRuntimeServicesData.
278314879Simp
279314879Simp  Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData, clears the
280314879Simp  buffer with zeros, and returns a pointer to the allocated buffer.  If AllocationSize is 0, then a
281314879Simp  valid buffer of 0 size is returned.  If there is not enough memory remaining to satisfy the
282314879Simp  request, then NULL is returned.
283314879Simp
284314879Simp  @param  AllocationSize        The number of bytes to allocate and zero.
285314879Simp
286314879Simp  @return A pointer to the allocated buffer or NULL if allocation fails.
287314879Simp
288314879Simp**/
289314879SimpVOID *
290314879SimpEFIAPI
291314879SimpAllocateRuntimeZeroPool (
292314879Simp  IN UINTN  AllocationSize
293314879Simp  );
294314879Simp
295314879Simp/**
296314879Simp  Allocates and zeros a buffer of type EfiReservedMemoryType.
297314879Simp
298314879Simp  Allocates the number bytes specified by AllocationSize of type EfiReservedMemoryType, clears the
299314879Simp  buffer with zeros, and returns a pointer to the allocated buffer.  If AllocationSize is 0, then a
300314879Simp  valid buffer of 0 size is returned.  If there is not enough memory remaining to satisfy the
301314879Simp  request, then NULL is returned.
302314879Simp
303314879Simp  @param  AllocationSize        The number of bytes to allocate and zero.
304314879Simp
305314879Simp  @return A pointer to the allocated buffer or NULL if allocation fails.
306314879Simp
307314879Simp**/
308314879SimpVOID *
309314879SimpEFIAPI
310314879SimpAllocateReservedZeroPool (
311314879Simp  IN UINTN  AllocationSize
312314879Simp  );
313314879Simp
314314879Simp/**
315314879Simp  Copies a buffer to an allocated buffer of type EfiBootServicesData.
316314879Simp
317314879Simp  Allocates the number bytes specified by AllocationSize of type EfiBootServicesData, copies
318314879Simp  AllocationSize bytes from Buffer to the newly allocated buffer, and returns a pointer to the
319314879Simp  allocated buffer.  If AllocationSize is 0, then a valid buffer of 0 size is returned.  If there
320314879Simp  is not enough memory remaining to satisfy the request, then NULL is returned.
321314879Simp
322314879Simp  If Buffer is NULL, then ASSERT().
323314879Simp  If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT().
324314879Simp
325314879Simp  @param  AllocationSize        The number of bytes to allocate and zero.
326314879Simp  @param  Buffer                The buffer to copy to the allocated buffer.
327314879Simp
328314879Simp  @return A pointer to the allocated buffer or NULL if allocation fails.
329314879Simp
330314879Simp**/
331314879SimpVOID *
332314879SimpEFIAPI
333314879SimpAllocateCopyPool (
334314879Simp  IN UINTN       AllocationSize,
335314879Simp  IN CONST VOID  *Buffer
336314879Simp  );
337314879Simp
338314879Simp/**
339314879Simp  Copies a buffer to an allocated buffer of type EfiRuntimeServicesData.
340314879Simp
341314879Simp  Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData, copies
342314879Simp  AllocationSize bytes from Buffer to the newly allocated buffer, and returns a pointer to the
343314879Simp  allocated buffer.  If AllocationSize is 0, then a valid buffer of 0 size is returned.  If there
344314879Simp  is not enough memory remaining to satisfy the request, then NULL is returned.
345314879Simp
346314879Simp  If Buffer is NULL, then ASSERT().
347314879Simp  If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT().
348314879Simp
349314879Simp  @param  AllocationSize        The number of bytes to allocate and zero.
350314879Simp  @param  Buffer                The buffer to copy to the allocated buffer.
351314879Simp
352314879Simp  @return A pointer to the allocated buffer or NULL if allocation fails.
353314879Simp
354314879Simp**/
355314879SimpVOID *
356314879SimpEFIAPI
357314879SimpAllocateRuntimeCopyPool (
358314879Simp  IN UINTN       AllocationSize,
359314879Simp  IN CONST VOID  *Buffer
360314879Simp  );
361314879Simp
362314879Simp/**
363314879Simp  Copies a buffer to an allocated buffer of type EfiReservedMemoryType.
364314879Simp
365314879Simp  Allocates the number bytes specified by AllocationSize of type EfiReservedMemoryType, copies
366314879Simp  AllocationSize bytes from Buffer to the newly allocated buffer, and returns a pointer to the
367314879Simp  allocated buffer.  If AllocationSize is 0, then a valid buffer of 0 size is returned.  If there
368314879Simp  is not enough memory remaining to satisfy the request, then NULL is returned.
369314879Simp
370314879Simp  If Buffer is NULL, then ASSERT().
371314879Simp  If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT().
372314879Simp
373314879Simp  @param  AllocationSize        The number of bytes to allocate and zero.
374314879Simp  @param  Buffer                The buffer to copy to the allocated buffer.
375314879Simp
376314879Simp  @return A pointer to the allocated buffer or NULL if allocation fails.
377314879Simp
378314879Simp**/
379314879SimpVOID *
380314879SimpEFIAPI
381314879SimpAllocateReservedCopyPool (
382314879Simp  IN UINTN       AllocationSize,
383314879Simp  IN CONST VOID  *Buffer
384314879Simp  );
385314879Simp
386314879Simp/**
387314879Simp  Reallocates a buffer of type EfiBootServicesData.
388314879Simp
389314879Simp  Allocates and zeros the number bytes specified by NewSize from memory of type
390314879Simp  EfiBootServicesData.  If OldBuffer is not NULL, then the smaller of OldSize and
391314879Simp  NewSize bytes are copied from OldBuffer to the newly allocated buffer, and
392314879Simp  OldBuffer is freed.  A pointer to the newly allocated buffer is returned.
393314879Simp  If NewSize is 0, then a valid buffer of 0 size is  returned.  If there is not
394314879Simp  enough memory remaining to satisfy the request, then NULL is returned.
395314879Simp
396314879Simp  If the allocation of the new buffer is successful and the smaller of NewSize and OldSize
397314879Simp  is greater than (MAX_ADDRESS - OldBuffer + 1), then ASSERT().
398314879Simp
399314879Simp  @param  OldSize        The size, in bytes, of OldBuffer.
400314879Simp  @param  NewSize        The size, in bytes, of the buffer to reallocate.
401314879Simp  @param  OldBuffer      The buffer to copy to the allocated buffer.  This is an optional
402314879Simp                         parameter that may be NULL.
403314879Simp
404314879Simp  @return A pointer to the allocated buffer or NULL if allocation fails.
405314879Simp
406314879Simp**/
407314879SimpVOID *
408314879SimpEFIAPI
409314879SimpReallocatePool (
410314879Simp  IN UINTN  OldSize,
411314879Simp  IN UINTN  NewSize,
412314879Simp  IN VOID   *OldBuffer  OPTIONAL
413314879Simp  );
414314879Simp
415314879Simp/**
416314879Simp  Reallocates a buffer of type EfiRuntimeServicesData.
417314879Simp
418314879Simp  Allocates and zeros the number bytes specified by NewSize from memory of type
419314879Simp  EfiRuntimeServicesData.  If OldBuffer is not NULL, then the smaller of OldSize and
420314879Simp  NewSize bytes are copied from OldBuffer to the newly allocated buffer, and
421314879Simp  OldBuffer is freed.  A pointer to the newly allocated buffer is returned.
422314879Simp  If NewSize is 0, then a valid buffer of 0 size is  returned.  If there is not
423314879Simp  enough memory remaining to satisfy the request, then NULL is returned.
424314879Simp
425314879Simp  If the allocation of the new buffer is successful and the smaller of NewSize and OldSize
426314879Simp  is greater than (MAX_ADDRESS - OldBuffer + 1), then ASSERT().
427314879Simp
428314879Simp  @param  OldSize        The size, in bytes, of OldBuffer.
429314879Simp  @param  NewSize        The size, in bytes, of the buffer to reallocate.
430314879Simp  @param  OldBuffer      The buffer to copy to the allocated buffer.  This is an optional
431314879Simp                         parameter that may be NULL.
432314879Simp
433314879Simp  @return A pointer to the allocated buffer or NULL if allocation fails.
434314879Simp
435314879Simp**/
436314879SimpVOID *
437314879SimpEFIAPI
438314879SimpReallocateRuntimePool (
439314879Simp  IN UINTN  OldSize,
440314879Simp  IN UINTN  NewSize,
441314879Simp  IN VOID   *OldBuffer  OPTIONAL
442314879Simp  );
443314879Simp
444314879Simp/**
445314879Simp  Reallocates a buffer of type EfiReservedMemoryType.
446314879Simp
447314879Simp  Allocates and zeros the number bytes specified by NewSize from memory of type
448314879Simp  EfiReservedMemoryType.  If OldBuffer is not NULL, then the smaller of OldSize and
449314879Simp  NewSize bytes are copied from OldBuffer to the newly allocated buffer, and
450314879Simp  OldBuffer is freed.  A pointer to the newly allocated buffer is returned.
451314879Simp  If NewSize is 0, then a valid buffer of 0 size is  returned.  If there is not
452314879Simp  enough memory remaining to satisfy the request, then NULL is returned.
453314879Simp
454314879Simp  If the allocation of the new buffer is successful and the smaller of NewSize and OldSize
455314879Simp  is greater than (MAX_ADDRESS - OldBuffer + 1), then ASSERT().
456314879Simp
457314879Simp  @param  OldSize        The size, in bytes, of OldBuffer.
458314879Simp  @param  NewSize        The size, in bytes, of the buffer to reallocate.
459314879Simp  @param  OldBuffer      The buffer to copy to the allocated buffer.  This is an optional
460314879Simp                         parameter that may be NULL.
461314879Simp
462314879Simp  @return A pointer to the allocated buffer or NULL if allocation fails.
463314879Simp
464314879Simp**/
465314879SimpVOID *
466314879SimpEFIAPI
467314879SimpReallocateReservedPool (
468314879Simp  IN UINTN  OldSize,
469314879Simp  IN UINTN  NewSize,
470314879Simp  IN VOID   *OldBuffer  OPTIONAL
471314879Simp  );
472314879Simp
473314879Simp/**
474314879Simp  Frees a buffer that was previously allocated with one of the pool allocation functions in the
475314879Simp  Memory Allocation Library.
476314879Simp
477314879Simp  Frees the buffer specified by Buffer.  Buffer must have been allocated on a previous call to the
478314879Simp  pool allocation services of the Memory Allocation Library.  If it is not possible to free pool
479314879Simp  resources, then this function will perform no actions.
480314879Simp
481314879Simp  If Buffer was not allocated with a pool allocation function in the Memory Allocation Library,
482314879Simp  then ASSERT().
483314879Simp
484314879Simp  @param  Buffer                Pointer to the buffer to free.
485314879Simp
486314879Simp**/
487314879SimpVOID
488314879SimpEFIAPI
489314879SimpFreePool (
490314879Simp  IN VOID   *Buffer
491314879Simp  );
492314879Simp
493314879Simp#endif
494