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