Standard Libraries for EDK II.
This set of three packages: AppPkg, StdLib, StdLibPrivateInternalFiles; contains the implementation of libraries based upon non-UEFI standards such as ISO/IEC-9899, the library portion of the C Language Standard, POSIX, etc. AppPkg contains applications that make use of the standard libraries defined in the StdLib Package. StdLib contains header (include) files and the implementations of the standard libraries. StdLibPrivateInternalFiles contains files for the exclusive use of the library implementations in StdLib. These files should never be directly referenced from applications or other code. git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@11600 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
226
StdLib/LibC/StdLib/Malloc.c
Normal file
226
StdLib/LibC/StdLib/Malloc.c
Normal file
@ -0,0 +1,226 @@
|
||||
/** @file
|
||||
Definitions for memory allocation routines: calloc, malloc, realloc, free.
|
||||
|
||||
The order and contiguity of storage allocated by successive calls to the
|
||||
calloc, malloc, and realloc functions is unspecified. The pointer returned
|
||||
if the allocation succeeds is suitably aligned so that it may be assigned to
|
||||
a pointer of any type of object and then used to access such an object or an
|
||||
array of such objects in the space allocated (until the space is explicitly
|
||||
freed or reallocated). Each such allocation shall yield a pointer to an
|
||||
object disjoint from any other object. The pointer returned points to the
|
||||
start (lowest byte address) of the allocated space. If the space can not be
|
||||
allocated, a null pointer is returned. If the size of the space requested
|
||||
is zero, the behavior is implementation-defined; the value returned shall be
|
||||
either a null pointer or a unique pointer. The value of a pointer that
|
||||
refers to freed space is indeterminate.
|
||||
|
||||
Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
*/
|
||||
#include <Base.h>
|
||||
#include <Uefi.h>
|
||||
#include <Library/MemoryAllocationLib.h>
|
||||
#include <Library/UefiBootServicesTableLib.h>
|
||||
#include <Library/BaseMemoryLib.h>
|
||||
#include <Library/DebugLib.h>
|
||||
|
||||
#include <LibConfig.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
|
||||
/** The UEFI functions do not provide a way to determine the size of an
|
||||
allocated region of memory given just a pointer to the start of that
|
||||
region. Since this is required for the implementation of realloc,
|
||||
the memory head structure from Core/Dxe/Mem/Pool.c has been reproduced
|
||||
here.
|
||||
|
||||
NOTE: If the UEFI implementation is changed, the realloc function may cease
|
||||
to function properly.
|
||||
**/
|
||||
#define POOL_HEAD_SIGNATURE SIGNATURE_32('p','h','d','0')
|
||||
typedef struct {
|
||||
UINT32 Signature;
|
||||
UINT32 Size;
|
||||
EFI_MEMORY_TYPE Type;
|
||||
UINTN Reserved;
|
||||
CHAR8 Data[1];
|
||||
} POOL_HEAD;
|
||||
|
||||
/****************************/
|
||||
|
||||
/** The malloc function allocates space for an object whose size is specified
|
||||
by size and whose value is indeterminate.
|
||||
|
||||
This implementation uses the UEFI memory allocation boot services to get a
|
||||
region of memory that is 8-byte aligned and of the specified size. The
|
||||
region is allocated with type EfiLoaderData.
|
||||
|
||||
@param size Size, in bytes, of the region to allocate.
|
||||
|
||||
@return NULL is returned if the space could not be allocated and errno
|
||||
contains the cause. Otherwise, a pointer to an 8-byte aligned
|
||||
region of the requested size is returned.<BR>
|
||||
If NULL is returned, errno may contain:
|
||||
- EINVAL: Requested Size is zero.
|
||||
- ENOMEM: Memory could not be allocated.
|
||||
**/
|
||||
void *
|
||||
malloc(size_t Size)
|
||||
{
|
||||
void *RetVal;
|
||||
EFI_STATUS Status;
|
||||
|
||||
if( Size == 0) {
|
||||
errno = EINVAL; // Make errno diffenent, just in case of a lingering ENOMEM.
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Status = gBS->AllocatePool( EfiLoaderData, (UINTN)Size, &RetVal);
|
||||
if( Status != EFI_SUCCESS) {
|
||||
RetVal = NULL;
|
||||
errno = ENOMEM;
|
||||
}
|
||||
return RetVal;
|
||||
}
|
||||
|
||||
/** The calloc function allocates space for an array of Num objects, each of
|
||||
whose size is Size. The space is initialized to all bits zero.
|
||||
|
||||
This implementation uses the UEFI memory allocation boot services to get a
|
||||
region of memory that is 8-byte aligned and of the specified size. The
|
||||
region is allocated with type EfiLoaderData.
|
||||
|
||||
@param Num Number of objects to allocate.
|
||||
@param Size Size, in bytes, of the objects to allocate space for.
|
||||
|
||||
@return NULL is returned if the space could not be allocated and errno
|
||||
contains the cause. Otherwise, a pointer to an 8-byte aligned
|
||||
region of the requested size is returned.
|
||||
**/
|
||||
void *
|
||||
calloc(size_t Num, size_t Size)
|
||||
{
|
||||
void *RetVal;
|
||||
size_t NumSize;
|
||||
|
||||
NumSize = Num * Size;
|
||||
if (NumSize == 0) {
|
||||
return NULL;
|
||||
}
|
||||
RetVal = malloc(NumSize);
|
||||
if( RetVal != NULL) {
|
||||
(VOID)ZeroMem( RetVal, NumSize);
|
||||
}
|
||||
return RetVal;
|
||||
}
|
||||
|
||||
/** The free function causes the space pointed to by Ptr to be deallocated,
|
||||
that is, made available for further allocation.
|
||||
|
||||
If Ptr is a null pointer, no action occurs. Otherwise, if the argument
|
||||
does not match a pointer earlier returned by the calloc, malloc, or realloc
|
||||
function, or if the space has been deallocated by a call to free or
|
||||
realloc, the behavior is undefined.
|
||||
|
||||
@param Ptr Pointer to a previously allocated region of memory to be freed.
|
||||
|
||||
**/
|
||||
void
|
||||
free(void *Ptr)
|
||||
{
|
||||
(void) gBS->FreePool (Ptr);
|
||||
}
|
||||
|
||||
/** The realloc function changes the size of the object pointed to by Ptr to
|
||||
the size specified by NewSize.
|
||||
|
||||
The contents of the object are unchanged up to the lesser of the new and
|
||||
old sizes. If the new size is larger, the value of the newly allocated
|
||||
portion of the object is indeterminate.
|
||||
|
||||
If Ptr is a null pointer, the realloc function behaves like the malloc
|
||||
function for the specified size.
|
||||
|
||||
If Ptr does not match a pointer earlier returned by the calloc, malloc, or
|
||||
realloc function, or if the space has been deallocated by a call to the free
|
||||
or realloc function, the behavior is undefined.
|
||||
|
||||
If the space cannot be allocated, the object pointed to by Ptr is unchanged.
|
||||
|
||||
If NewSize is zero and Ptr is not a null pointer, the object it points to
|
||||
is freed.
|
||||
|
||||
This implementation uses the UEFI memory allocation boot services to get a
|
||||
region of memory that is 8-byte aligned and of the specified size. The
|
||||
region is allocated with type EfiLoaderData.
|
||||
|
||||
The following combinations of Ptr and NewSize can occur:<BR>
|
||||
Ptr NewSize<BR>
|
||||
-------- -------------------<BR>
|
||||
- NULL 0 Returns NULL;
|
||||
- NULL > 0 Same as malloc(NewSize)
|
||||
- invalid X Returns NULL;
|
||||
- valid NewSize >= OldSize Returns malloc(NewSize) with Oldsize bytes copied from Ptr
|
||||
- valid NewSize < OldSize Returns new buffer with Oldsize bytes copied from Ptr
|
||||
- valid 0 Return NULL. Frees Ptr.
|
||||
|
||||
|
||||
@param Ptr Pointer to a previously allocated region of memory to be resized.
|
||||
@param NewSize Size, in bytes, of the new object to allocate space for.
|
||||
|
||||
@return NULL is returned if the space could not be allocated and errno
|
||||
contains the cause. Otherwise, a pointer to an 8-byte aligned
|
||||
region of the requested size is returned. If NewSize is zero,
|
||||
NULL is returned and errno will be unchanged.
|
||||
**/
|
||||
void *
|
||||
realloc(void *Ptr, size_t NewSize)
|
||||
{
|
||||
void *RetVal = NULL;
|
||||
POOL_HEAD *Head;
|
||||
UINTN OldSize = 0;
|
||||
UINTN NumCpy;
|
||||
|
||||
// Find out the size of the OLD memory region
|
||||
if( Ptr != NULL) {
|
||||
Head = BASE_CR (Ptr, POOL_HEAD, Data);
|
||||
assert(Head != NULL);
|
||||
if (Head->Signature != POOL_HEAD_SIGNATURE) {
|
||||
errno = EFAULT;
|
||||
return NULL;
|
||||
}
|
||||
OldSize = Head->Size;
|
||||
}
|
||||
|
||||
// At this point, Ptr is either NULL or a valid pointer to an allocated space
|
||||
|
||||
if( NewSize > 0) {
|
||||
RetVal = malloc(NewSize); // Get the NEW memory region
|
||||
if( Ptr != NULL) { // If there is an OLD region...
|
||||
if( RetVal != NULL) { // and the NEW region was successfully allocated
|
||||
NumCpy = OldSize;
|
||||
if( OldSize > NewSize) {
|
||||
NumCpy = NewSize;
|
||||
}
|
||||
(VOID)CopyMem( RetVal, Ptr, NumCpy); // Copy old data to the new region.
|
||||
free( Ptr); // and reclaim the old region.
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if( Ptr != NULL) {
|
||||
free( Ptr); // Reclaim the old region.
|
||||
}
|
||||
}
|
||||
|
||||
return RetVal;
|
||||
}
|
Reference in New Issue
Block a user