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*
UefiDecompress(PyObject * Self,PyObject * Args)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*
FrameworkDecompress(PyObject * Self,PyObject * Args)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*
UefiCompress(PyObject * Self,PyObject * Args)177 UefiCompress(
178   PyObject    *Self,
179   PyObject    *Args
180   )
181 {
182   return NULL;
183 }
184 
185 
186 STATIC
187 PyObject*
FrameworkCompress(PyObject * Self,PyObject * Args)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
initEfiCompressor(VOID)208 initEfiCompressor(VOID) {
209   Py_InitModule3("EfiCompressor", EfiCompressor_Funcs, "EFI Compression Algorithm Extension Module");
210 }
211 
212 
213