Home | History | Annotate | Download | only in PyEfiCompressor
      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