mirror of
https://github.com/CloverHackyColor/CloverBootloader.git
synced 2024-11-30 12:43:41 +01:00
c1f2f96041
Signed-off-by: Sergey Isakov <isakov-sl@bk.ru>
291 lines
9.4 KiB
C
291 lines
9.4 KiB
C
/** @file
|
|
|
|
OcTemplateLib
|
|
|
|
Copyright (c) 2018, vit9696
|
|
|
|
All rights reserved.
|
|
|
|
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.
|
|
|
|
**/
|
|
|
|
#ifndef OC_TEMPLATE_LIB_H
|
|
#define OC_TEMPLATE_LIB_H
|
|
|
|
#include <Library/BaseMemoryLib.h>
|
|
|
|
//
|
|
// Common structor prototype.
|
|
//
|
|
typedef
|
|
VOID
|
|
(*OC_STRUCTOR) (
|
|
VOID *Ptr,
|
|
UINT32 Size
|
|
);
|
|
|
|
//
|
|
// Private primitives for type generations
|
|
//
|
|
|
|
#define PRIV_OC_STRUCTOR_IGNORE(...)
|
|
#define PRIV_OC_STRUCTOR_EXPAND(...) __VA_ARGS__
|
|
|
|
#define PRIV_OC_SELECT_NEXT_INNER(Dummy, Next, ...) Next
|
|
//
|
|
// Without this layer of indirection, MSVC evaluates __VA_ARGS__ early and
|
|
// PRIV_OC_SELECT_NEXT_INNER receives only two arguments, the second always
|
|
// being Unused as per PRIV_OC_SELECT_NEXT.
|
|
//
|
|
#define PRIV_OC_SELECT_NEXT_INNER_INDIR(...) PRIV_OC_SELECT_NEXT_INNER __VA_ARGS__
|
|
#define PRIV_OC_SELECT_NEXT(...) PRIV_OC_SELECT_NEXT_INNER_INDIR((__VA_ARGS__, Unused))
|
|
#define PRIV_OC_REMOVE_NEXT(...) , do { } while (0),
|
|
|
|
#define PRIV_OC_DECLARE_STRUCT_MEMBER(Type, Name, Suffix, Constructor, Destructor) \
|
|
Type Name Suffix;
|
|
|
|
#define PRIV_OC_CONSTRUCT_STRUCT_MEMBER(Type, Name, Suffix, Constructor, Destructor) \
|
|
.Name = Constructor,
|
|
|
|
#define PRIV_OC_DESTRUCT_STRUCT_MEMBER(Type, Name, Suffix, Constructor, Destructor) \
|
|
PRIV_OC_SELECT_NEXT(PRIV_OC_REMOVE_NEXT Destructor, Destructor(&Obj->Name, sizeof (Type Suffix)));
|
|
|
|
#define PRIV_OC_INVOKE_DESTRUCTOR(Destructor, Obj, Size) \
|
|
PRIV_OC_SELECT_NEXT(PRIV_OC_REMOVE_NEXT Destructor, Destructor(Obj, Size))
|
|
|
|
#define PRIV_NO_KEY_TYPE UINT8
|
|
|
|
//
|
|
// Declare structure type NAME. Construction and destruction interfaces will also be
|
|
// available with corresponding prototypes:
|
|
// VOID NAME_CONSTRUCT(Void *Ptr, UINTN Size);
|
|
// VOID NAME_DESTRUCT(Void *Ptr, UINTN Size);
|
|
//
|
|
// Field information will be retrieved from NAME_FIELDS X-Macro, written as follows:
|
|
#if 0
|
|
#define NAME_FIELDS(_, __) \
|
|
_(Type, Name, Type Suffix, __(Constant Initializer), Destructor Function) \
|
|
_(Type, Name, Type Suffix, OC_CONSTR(Type, _, __), OC_DESTR(Type))
|
|
#endif
|
|
//
|
|
|
|
#define OC_DECLARE(Name) \
|
|
typedef struct Name ## _ { \
|
|
Name ## _FIELDS (PRIV_OC_DECLARE_STRUCT_MEMBER, PRIV_OC_STRUCTOR_IGNORE) \
|
|
} Name; \
|
|
VOID Name ## _CONSTRUCT(VOID *Ptr, UINT32 Size); \
|
|
VOID Name ## _DESTRUCT(VOID *Ptr, UINT32 Size);
|
|
|
|
//
|
|
// Generate constructors and destructors for structure type NAME.
|
|
// Second argument permits to do extra actions prior to field destruction.
|
|
// Pass () to the second argument to ignore this option.
|
|
//
|
|
#define OC_STRUCTORS(Name, Destructor) \
|
|
VOID Name ## _CONSTRUCT(VOID *Ptr, UINT32 Size) { \
|
|
STATIC Name Obj = { \
|
|
Name ## _FIELDS(PRIV_OC_CONSTRUCT_STRUCT_MEMBER, PRIV_OC_STRUCTOR_EXPAND) \
|
|
}; \
|
|
CopyMem (Ptr, &Obj, sizeof (Name)); \
|
|
} \
|
|
VOID Name ## _DESTRUCT(VOID *Ptr, UINT32 Size) { \
|
|
Name *Obj = (Name *) Ptr; (VOID) Obj; \
|
|
PRIV_OC_INVOKE_DESTRUCTOR(Destructor, Obj, sizeof (Name)); \
|
|
Name ## _FIELDS(PRIV_OC_DESTRUCT_STRUCT_MEMBER, PRIV_OC_STRUCTOR_EXPAND) \
|
|
}
|
|
|
|
//
|
|
// Use previously defined structure constructor or destructor
|
|
// FIXME: We need to use these recursively, and normally one would implement
|
|
// it with deferred execution, like this:
|
|
// #define OC_CONSTR_REAL(A, _, __) ({A ## _FIELDS(_, __)})
|
|
// #define OC_CONSTR_REAL_ID() OC_CONSTR_REAL
|
|
// #define OC_CONSTR DEFER(OC_CONSTR_REAL_ID)()
|
|
// However, this will not work in this exact case, as _, which itself is a macro,
|
|
// changes the expansion order. The right fix here is to entirely remove the mess
|
|
// and use external tool for template generation.
|
|
//
|
|
#define OC_CONSTR(A, _, __) {A ## _FIELDS(_, __)}
|
|
#define OC_CONSTR1(A, _, __) {A ## _FIELDS(_, __)}
|
|
#define OC_CONSTR2(A, _, __) {A ## _FIELDS(_, __)}
|
|
#define OC_CONSTR3(A, _, __) {A ## _FIELDS(_, __)}
|
|
#define OC_CONSTR5(A, _, __) {A ## _FIELDS(_, __)}
|
|
#define OC_DESTR(A) A ## _DESTRUCT
|
|
|
|
//
|
|
// Generate array-like blob (string, data, metadata) of type Type,
|
|
// Count static size, MaxSize is real size, and default value Default.
|
|
//
|
|
#define OC_BLOB(Type, Count, Default, _, __) \
|
|
_(UINT32 , Size , , 0 , OcZeroField ) \
|
|
_(UINT32 , MaxSize , , sizeof (Type Count) , OcZeroField ) \
|
|
_(Type * , DynValue , , NULL , OcFreePointer ) \
|
|
_(Type , Value , Count , __(Default) , () )
|
|
|
|
#define OC_BLOB_STRUCTORS(Name) \
|
|
OC_STRUCTORS(Name, ())
|
|
|
|
#define OC_BLOB_CONSTR(Type, Constructor, SizeConstructor, _, __) \
|
|
__({.Size = SizeConstructor, .MaxSize = sizeof (((Type *)0)->Value), .DynValue = NULL, .Value = Constructor})
|
|
|
|
//
|
|
// Generate map-like container with key elements of type KeyType, OC_BLOB derivative,
|
|
// value types of Type constructed by Constructor and destructed by Destructor:
|
|
#if 0
|
|
#define CONT_FIELDS(_, __) \
|
|
OC_MAP (KEY, ELEM, _, __)
|
|
OC_DECLARE (CONT)
|
|
#endif
|
|
//
|
|
|
|
#define OC_MAP(KeyType, Type, _, __) \
|
|
_(UINT32 , Count , , 0 , () ) \
|
|
_(UINT32 , AllocCount , , 0 , () ) \
|
|
_(OC_STRUCTOR , Construct , , Type ## _CONSTRUCT , () ) \
|
|
_(OC_STRUCTOR , Destruct , , Type ## _DESTRUCT , () ) \
|
|
_(Type ** , Values , , NULL , () ) \
|
|
_(UINT32 , ValueSize , , sizeof (Type) , () ) \
|
|
_(UINT32 , KeySize , , sizeof (KeyType) , () ) \
|
|
_(OC_STRUCTOR , KeyConstruct , , KeyType ## _CONSTRUCT , () ) \
|
|
_(OC_STRUCTOR , KeyDestruct , , KeyType ## _DESTRUCT , () ) \
|
|
_(KeyType ** , Keys , , NULL , () )
|
|
|
|
#define OC_MAP_STRUCTORS(Name) \
|
|
OC_STRUCTORS(Name, OcFreeMap)
|
|
|
|
//
|
|
// Generate array-like container with elements of type Type, constructed
|
|
// by Constructor and destructed by Destructor.
|
|
#if 0
|
|
#define CONT_FIELDS(_, __) \
|
|
OC_ARRAY (ELEM, _, __)
|
|
OC_DECLARE (CONT)
|
|
#endif
|
|
//
|
|
|
|
#define OC_ARRAY(Type, _, __) \
|
|
_(UINT32 , Count , , 0 , () ) \
|
|
_(UINT32 , AllocCount , , 0 , () ) \
|
|
_(OC_STRUCTOR , Construct , , Type ## _CONSTRUCT , () ) \
|
|
_(OC_STRUCTOR , Destruct , , Type ## _DESTRUCT , () ) \
|
|
_(Type ** , Values , , NULL , () ) \
|
|
_(UINT32 , ValueSize , , sizeof (Type) , () )
|
|
|
|
#define OC_ARRAY_STRUCTORS(Name) \
|
|
OC_STRUCTORS(Name, OcFreeArray)
|
|
|
|
//
|
|
// Free dynamically allocated memory if non NULL.
|
|
// Note, that the first argument is actually VOID **.
|
|
//
|
|
VOID
|
|
OcFreePointer (
|
|
VOID *Pointer,
|
|
UINT32 Size
|
|
);
|
|
|
|
//
|
|
// Zero field memory.
|
|
//
|
|
VOID
|
|
OcZeroField (
|
|
VOID *Pointer,
|
|
UINT32 Size
|
|
);
|
|
|
|
//
|
|
// Do not invoke any actions at destruction.
|
|
//
|
|
VOID
|
|
OcDestructEmpty (
|
|
VOID *Pointer,
|
|
UINT32 Size
|
|
);
|
|
|
|
//
|
|
// OC_MAP-like destructor.
|
|
//
|
|
VOID
|
|
OcFreeMap (
|
|
VOID *Pointer,
|
|
UINT32 Size
|
|
);
|
|
|
|
//
|
|
// OC_ARRAY-like destructor.
|
|
//
|
|
VOID
|
|
OcFreeArray (
|
|
VOID *Pointer,
|
|
UINT32 Size
|
|
);
|
|
|
|
//
|
|
// Prepare memory for blob at Pointer to contain Size bytes.
|
|
// Assignable size may be returned via OutSize.
|
|
// This method guarantees not to overwrite "Default" value,
|
|
// but may destroy the previous value.
|
|
// NULL is returned on allocation failure.
|
|
//
|
|
VOID *
|
|
OcBlobAllocate (
|
|
VOID *Pointer,
|
|
UINT32 Size,
|
|
UINT32 **OutSize OPTIONAL
|
|
);
|
|
|
|
//
|
|
// Obtain blob value
|
|
//
|
|
#define OC_BLOB_GET(Blob) (((Blob)->DynValue) != NULL ? ((Blob)->DynValue) : ((Blob)->Value))
|
|
|
|
//
|
|
// Insert new empty element into the OC_MAP or OC_ARRAY, depending
|
|
// on Key value.
|
|
//
|
|
BOOLEAN
|
|
OcListEntryAllocate (
|
|
VOID *Pointer,
|
|
VOID **Value,
|
|
VOID **Key
|
|
);
|
|
|
|
//
|
|
// Some useful generic types
|
|
// OC_STRING - implements support for resizable ASCII strings.
|
|
// OC_DATA - implements support for resizable data blobs.
|
|
// OC_ASSOC - implements support for maps with ASCII keys and data values.
|
|
//
|
|
#define OC_STRING_FIELDS(_, __) \
|
|
OC_BLOB (CHAR8, [64], {0}, _, __)
|
|
OC_DECLARE (OC_STRING)
|
|
|
|
#define OC_STRING_CONSTR(Constructor, _, __) \
|
|
OC_BLOB_CONSTR (OC_STRING, __(Constructor), sizeof (Constructor), _, __)
|
|
|
|
#define OC_ESTRING_CONSTR(_, __) \
|
|
OC_BLOB_CONSTR (OC_STRING, __(""), 0, _, __)
|
|
|
|
#define OC_DATA_FIELDS(_, __) \
|
|
OC_BLOB (UINT8, [64], {0}, _, __)
|
|
OC_DECLARE (OC_DATA)
|
|
|
|
#define OC_EDATA_CONSTR(_, __) \
|
|
OC_BLOB_CONSTR (OC_DATA, __({0}), 0, _, __)
|
|
|
|
#define OC_DATA_CONSTR(Constructor, _, __) \
|
|
OC_BLOB_CONSTR (OC_DATA, __(Constructor), sizeof ((UINT8[]) Constructor), _, __)
|
|
|
|
#define OC_ASSOC_FIELDS(_, __) \
|
|
OC_MAP (OC_STRING, OC_DATA, _, __)
|
|
OC_DECLARE (OC_ASSOC)
|
|
|
|
#endif // OC_TEMPLATE_LIB_H
|