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