audk/BaseTools/Source/C/PyEfiCompressor/EfiCompressor.c

207 lines
5.1 KiB
C

/** @file
Efi Compressor
Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include <Python.h>
#include <Decompress.h>
/*
UefiDecompress(data_buffer, size, original_size)
*/
STATIC
PyObject*
UefiDecompress(
PyObject *Self,
PyObject *Args
)
{
PyObject *SrcData;
UINT32 SrcDataSize;
UINT32 DstDataSize;
UINTN Status;
UINT8 *SrcBuf;
UINT8 *DstBuf;
UINT8 *TmpBuf;
Py_ssize_t SegNum;
Py_ssize_t Index;
Status = PyArg_ParseTuple(
Args,
"Oi",
&SrcData,
&SrcDataSize
);
if (Status == 0) {
return NULL;
}
if (SrcData->ob_type->tp_as_buffer == NULL
|| SrcData->ob_type->tp_as_buffer->bf_getreadbuffer == NULL
|| SrcData->ob_type->tp_as_buffer->bf_getsegcount == NULL) {
PyErr_SetString(PyExc_Exception, "First argument is not a buffer\n");
return NULL;
}
// Because some Python objects which support "buffer" protocol have more than one
// memory segment, we have to copy them into a contiguous memory.
SrcBuf = PyMem_Malloc(SrcDataSize);
if (SrcBuf == NULL) {
PyErr_SetString(PyExc_Exception, "Not enough memory\n");
goto ERROR;
}
SegNum = SrcData->ob_type->tp_as_buffer->bf_getsegcount((PyObject *)SrcData, NULL);
TmpBuf = SrcBuf;
for (Index = 0; Index < SegNum; ++Index) {
VOID *BufSeg;
Py_ssize_t Len;
Len = SrcData->ob_type->tp_as_buffer->bf_getreadbuffer((PyObject *)SrcData, Index, &BufSeg);
if (Len < 0) {
PyErr_SetString(PyExc_Exception, "Buffer segment is not available\n");
goto ERROR;
}
memcpy(TmpBuf, BufSeg, Len);
TmpBuf += Len;
}
Status = Extract((VOID *)SrcBuf, SrcDataSize, (VOID **)&DstBuf, &DstDataSize, 1);
if (Status != EFI_SUCCESS) {
PyErr_SetString(PyExc_Exception, "Failed to decompress\n");
goto ERROR;
}
return PyBuffer_FromMemory(DstBuf, (Py_ssize_t)DstDataSize);
ERROR:
if (SrcBuf != NULL) {
free(SrcBuf);
}
if (DstBuf != NULL) {
free(DstBuf);
}
return NULL;
}
STATIC
PyObject*
FrameworkDecompress(
PyObject *Self,
PyObject *Args
)
{
PyObject *SrcData;
UINT32 SrcDataSize;
UINT32 DstDataSize;
UINTN Status;
UINT8 *SrcBuf;
UINT8 *DstBuf;
UINT8 *TmpBuf;
Py_ssize_t SegNum;
Py_ssize_t Index;
Status = PyArg_ParseTuple(
Args,
"Oi",
&SrcData,
&SrcDataSize
);
if (Status == 0) {
return NULL;
}
if (SrcData->ob_type->tp_as_buffer == NULL
|| SrcData->ob_type->tp_as_buffer->bf_getreadbuffer == NULL
|| SrcData->ob_type->tp_as_buffer->bf_getsegcount == NULL) {
PyErr_SetString(PyExc_Exception, "First argument is not a buffer\n");
return NULL;
}
// Because some Python objects which support "buffer" protocol have more than one
// memory segment, we have to copy them into a contiguous memory.
SrcBuf = PyMem_Malloc(SrcDataSize);
if (SrcBuf == NULL) {
PyErr_SetString(PyExc_Exception, "Not enough memory\n");
goto ERROR;
}
SegNum = SrcData->ob_type->tp_as_buffer->bf_getsegcount((PyObject *)SrcData, NULL);
TmpBuf = SrcBuf;
for (Index = 0; Index < SegNum; ++Index) {
VOID *BufSeg;
Py_ssize_t Len;
Len = SrcData->ob_type->tp_as_buffer->bf_getreadbuffer((PyObject *)SrcData, Index, &BufSeg);
if (Len < 0) {
PyErr_SetString(PyExc_Exception, "Buffer segment is not available\n");
goto ERROR;
}
memcpy(TmpBuf, BufSeg, Len);
TmpBuf += Len;
}
Status = Extract((VOID *)SrcBuf, SrcDataSize, (VOID **)&DstBuf, &DstDataSize, 2);
if (Status != EFI_SUCCESS) {
PyErr_SetString(PyExc_Exception, "Failed to decompress\n");
goto ERROR;
}
return PyString_FromStringAndSize((CONST INT8*)DstBuf, (Py_ssize_t)DstDataSize);
ERROR:
if (SrcBuf != NULL) {
free(SrcBuf);
}
if (DstBuf != NULL) {
free(DstBuf);
}
return NULL;
}
STATIC
PyObject*
UefiCompress(
PyObject *Self,
PyObject *Args
)
{
return NULL;
}
STATIC
PyObject*
FrameworkCompress(
PyObject *Self,
PyObject *Args
)
{
return NULL;
}
STATIC INT8 DecompressDocs[] = "Decompress(): Decompress data using UEFI standard algorithm\n";
STATIC INT8 CompressDocs[] = "Compress(): Compress data using UEFI standard algorithm\n";
STATIC PyMethodDef EfiCompressor_Funcs[] = {
{"UefiDecompress", (PyCFunction)UefiDecompress, METH_VARARGS, DecompressDocs},
{"UefiCompress", (PyCFunction)UefiCompress, METH_VARARGS, DecompressDocs},
{"FrameworkDecompress", (PyCFunction)FrameworkDecompress, METH_VARARGS, DecompressDocs},
{"FrameworkCompress", (PyCFunction)FrameworkCompress, METH_VARARGS, DecompressDocs},
{NULL, NULL, 0, NULL}
};
PyMODINIT_FUNC
initEfiCompressor(VOID) {
Py_InitModule3("EfiCompressor", EfiCompressor_Funcs, "EFI Compression Algorithm Extension Module");
}