1 /** @file 2 Efi Compressor 3 4 Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.<BR> 5 This program and the accompanying materials are licensed and made available 6 under the terms and conditions of the BSD License which accompanies this 7 distribution. The full text of the license may be found at 8 http://opensource.org/licenses/bsd-license.php 9 10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 12 13 **/ 14 15 #include <Python.h> 16 #include <Decompress.h> 17 18 /* 19 UefiDecompress(data_buffer, size, original_size) 20 */ 21 STATIC 22 PyObject* 23 UefiDecompress( 24 PyObject *Self, 25 PyObject *Args 26 ) 27 { 28 PyObject *SrcData; 29 UINT32 SrcDataSize; 30 UINT32 DstDataSize; 31 UINTN Status; 32 UINT8 *SrcBuf; 33 UINT8 *DstBuf; 34 UINT8 *TmpBuf; 35 Py_ssize_t SegNum; 36 Py_ssize_t Index; 37 38 Status = PyArg_ParseTuple( 39 Args, 40 "Oi", 41 &SrcData, 42 &SrcDataSize 43 ); 44 if (Status == 0) { 45 return NULL; 46 } 47 48 if (SrcData->ob_type->tp_as_buffer == NULL 49 || SrcData->ob_type->tp_as_buffer->bf_getreadbuffer == NULL 50 || SrcData->ob_type->tp_as_buffer->bf_getsegcount == NULL) { 51 PyErr_SetString(PyExc_Exception, "First argument is not a buffer\n"); 52 return NULL; 53 } 54 55 // Because some Python objects which support "buffer" protocol have more than one 56 // memory segment, we have to copy them into a contiguous memory. 57 SrcBuf = PyMem_Malloc(SrcDataSize); 58 if (SrcBuf == NULL) { 59 PyErr_SetString(PyExc_Exception, "Not enough memory\n"); 60 goto ERROR; 61 } 62 63 SegNum = SrcData->ob_type->tp_as_buffer->bf_getsegcount((PyObject *)SrcData, NULL); 64 TmpBuf = SrcBuf; 65 for (Index = 0; Index < SegNum; ++Index) { 66 VOID *BufSeg; 67 Py_ssize_t Len; 68 69 Len = SrcData->ob_type->tp_as_buffer->bf_getreadbuffer((PyObject *)SrcData, Index, &BufSeg); 70 if (Len < 0) { 71 PyErr_SetString(PyExc_Exception, "Buffer segment is not available\n"); 72 goto ERROR; 73 } 74 memcpy(TmpBuf, BufSeg, Len); 75 TmpBuf += Len; 76 } 77 78 Status = Extract((VOID *)SrcBuf, SrcDataSize, (VOID **)&DstBuf, &DstDataSize, 1); 79 if (Status != EFI_SUCCESS) { 80 PyErr_SetString(PyExc_Exception, "Failed to decompress\n"); 81 goto ERROR; 82 } 83 84 return PyBuffer_FromMemory(DstBuf, (Py_ssize_t)DstDataSize); 85 86 ERROR: 87 if (SrcBuf != NULL) { 88 free(SrcBuf); 89 } 90 91 if (DstBuf != NULL) { 92 free(DstBuf); 93 } 94 return NULL; 95 } 96 97 98 STATIC 99 PyObject* 100 FrameworkDecompress( 101 PyObject *Self, 102 PyObject *Args 103 ) 104 { 105 PyObject *SrcData; 106 UINT32 SrcDataSize; 107 UINT32 DstDataSize; 108 UINTN Status; 109 UINT8 *SrcBuf; 110 UINT8 *DstBuf; 111 UINT8 *TmpBuf; 112 Py_ssize_t SegNum; 113 Py_ssize_t Index; 114 115 Status = PyArg_ParseTuple( 116 Args, 117 "Oi", 118 &SrcData, 119 &SrcDataSize 120 ); 121 if (Status == 0) { 122 return NULL; 123 } 124 125 if (SrcData->ob_type->tp_as_buffer == NULL 126 || SrcData->ob_type->tp_as_buffer->bf_getreadbuffer == NULL 127 || SrcData->ob_type->tp_as_buffer->bf_getsegcount == NULL) { 128 PyErr_SetString(PyExc_Exception, "First argument is not a buffer\n"); 129 return NULL; 130 } 131 132 // Because some Python objects which support "buffer" protocol have more than one 133 // memory segment, we have to copy them into a contiguous memory. 134 SrcBuf = PyMem_Malloc(SrcDataSize); 135 if (SrcBuf == NULL) { 136 PyErr_SetString(PyExc_Exception, "Not enough memory\n"); 137 goto ERROR; 138 } 139 140 SegNum = SrcData->ob_type->tp_as_buffer->bf_getsegcount((PyObject *)SrcData, NULL); 141 TmpBuf = SrcBuf; 142 for (Index = 0; Index < SegNum; ++Index) { 143 VOID *BufSeg; 144 Py_ssize_t Len; 145 146 Len = SrcData->ob_type->tp_as_buffer->bf_getreadbuffer((PyObject *)SrcData, Index, &BufSeg); 147 if (Len < 0) { 148 PyErr_SetString(PyExc_Exception, "Buffer segment is not available\n"); 149 goto ERROR; 150 } 151 memcpy(TmpBuf, BufSeg, Len); 152 TmpBuf += Len; 153 } 154 155 Status = Extract((VOID *)SrcBuf, SrcDataSize, (VOID **)&DstBuf, &DstDataSize, 2); 156 if (Status != EFI_SUCCESS) { 157 PyErr_SetString(PyExc_Exception, "Failed to decompress\n"); 158 goto ERROR; 159 } 160 161 return PyString_FromStringAndSize((CONST INT8*)DstBuf, (Py_ssize_t)DstDataSize); 162 163 ERROR: 164 if (SrcBuf != NULL) { 165 free(SrcBuf); 166 } 167 168 if (DstBuf != NULL) { 169 free(DstBuf); 170 } 171 return NULL; 172 } 173 174 175 STATIC 176 PyObject* 177 UefiCompress( 178 PyObject *Self, 179 PyObject *Args 180 ) 181 { 182 return NULL; 183 } 184 185 186 STATIC 187 PyObject* 188 FrameworkCompress( 189 PyObject *Self, 190 PyObject *Args 191 ) 192 { 193 return NULL; 194 } 195 196 STATIC INT8 DecompressDocs[] = "Decompress(): Decompress data using UEFI standard algorithm\n"; 197 STATIC INT8 CompressDocs[] = "Compress(): Compress data using UEFI standard algorithm\n"; 198 199 STATIC PyMethodDef EfiCompressor_Funcs[] = { 200 {"UefiDecompress", (PyCFunction)UefiDecompress, METH_VARARGS, DecompressDocs}, 201 {"UefiCompress", (PyCFunction)UefiCompress, METH_VARARGS, DecompressDocs}, 202 {"FrameworkDecompress", (PyCFunction)FrameworkDecompress, METH_VARARGS, DecompressDocs}, 203 {"FrameworkCompress", (PyCFunction)FrameworkCompress, METH_VARARGS, DecompressDocs}, 204 {NULL, NULL, 0, NULL} 205 }; 206 207 PyMODINIT_FUNC 208 initEfiCompressor(VOID) { 209 Py_InitModule3("EfiCompressor", EfiCompressor_Funcs, "EFI Compression Algorithm Extension Module"); 210 } 211 212 213