Changed the interface parameters to be more general
[people/mcb30/basetools.git] / Source / C / PyEfiCompressor / EfiCompressor.c
1 #include <Python.h>\r
2 #include <Decompress.h>\r
3 \r
4 /*\r
5  UefiDecompress(data_buffer, size, original_size)\r
6 */\r
7 STATIC\r
8 PyObject*\r
9 UefiDecompress(\r
10   PyObject    *Self,\r
11   PyObject    *Args\r
12   )\r
13 {\r
14   PyObject      *SrcData;\r
15   UINT32        SrcDataSize;\r
16   UINT32        DstDataSize;\r
17   UINTN         Status;\r
18   UINT8         *SrcBuf;\r
19   UINT8         *DstBuf;\r
20   UINT8         *TmpBuf;\r
21   Py_ssize_t    SegNum;\r
22   Py_ssize_t    Index;\r
23 \r
24   Status = PyArg_ParseTuple(\r
25             Args,\r
26             "Oii",\r
27             &SrcData,\r
28             &SrcDataSize,\r
29             &DstDataSize\r
30             );\r
31   if (Status == 0) {\r
32     return NULL;\r
33   }\r
34 \r
35   if (SrcData->ob_type->tp_as_buffer == NULL\r
36       || SrcData->ob_type->tp_as_buffer->bf_getreadbuffer == NULL\r
37       || SrcData->ob_type->tp_as_buffer->bf_getsegcount == NULL) {\r
38     PyErr_SetString(PyExc_Exception, "First argument is not a buffer\n");\r
39     return NULL;\r
40   }\r
41 \r
42   // Because some Python objects which support "buffer" protocol have more than one\r
43   // memory segment, we have to copy them into a contiguous memory.\r
44   SrcBuf = malloc(SrcDataSize);\r
45   if (SrcBuf == NULL) {\r
46     PyErr_SetString(PyExc_Exception, "Not enough memory\n");\r
47     goto ERROR;\r
48   }\r
49 \r
50   SegNum = SrcData->ob_type->tp_as_buffer->bf_getsegcount((PyObject *)SrcData, NULL);\r
51   TmpBuf = SrcBuf;\r
52   for (Index = 0; Index < SegNum; ++Index) {\r
53     VOID *BufSeg;\r
54     Py_ssize_t Len;\r
55 \r
56     Len = SrcData->ob_type->tp_as_buffer->bf_getreadbuffer((PyObject *)SrcData, Index, &BufSeg);\r
57     if (Len < 0) {\r
58       PyErr_SetString(PyExc_Exception, "Buffer segment is not available\n");\r
59       goto ERROR;\r
60     }\r
61     memcpy(TmpBuf, BufSeg, Len);\r
62     TmpBuf += Len;\r
63   }\r
64 \r
65   Status = Extract((VOID *)SrcBuf, SrcDataSize, (VOID **)&DstBuf, &DstDataSize, 1);\r
66   if (Status != EFI_SUCCESS) {\r
67     PyErr_SetString(PyExc_Exception, "Failed to decompress\n");\r
68     goto ERROR;\r
69   }\r
70 \r
71   return PyBuffer_FromMemory(DstBuf, (Py_ssize_t)DstDataSize);\r
72 \r
73 ERROR:\r
74   if (SrcBuf != NULL) {\r
75     free(SrcBuf);\r
76   }\r
77 \r
78   if (DstBuf != NULL) {\r
79     free(DstBuf);\r
80   }\r
81   return NULL;\r
82 }\r
83 \r
84 \r
85 STATIC\r
86 PyObject*\r
87 FrameworkDecompress(\r
88   PyObject    *Self,\r
89   PyObject    *Args\r
90   )\r
91 {\r
92   PyObject      *SrcData;\r
93   UINT32        SrcDataSize;\r
94   UINT32        DstDataSize;\r
95   UINTN         Status;\r
96   UINT8         *SrcBuf;\r
97   UINT8         *DstBuf;\r
98   UINT8         *TmpBuf;\r
99   Py_ssize_t    SegNum;\r
100   Py_ssize_t    Index;\r
101 \r
102   Status = PyArg_ParseTuple(\r
103             Args,\r
104             "Oii",\r
105             &SrcData,\r
106             &SrcDataSize,\r
107             &DstDataSize\r
108             );\r
109   if (Status == 0) {\r
110     return NULL;\r
111   }\r
112 \r
113   if (SrcData->ob_type->tp_as_buffer == NULL\r
114       || SrcData->ob_type->tp_as_buffer->bf_getreadbuffer == NULL\r
115       || SrcData->ob_type->tp_as_buffer->bf_getsegcount == NULL) {\r
116     PyErr_SetString(PyExc_Exception, "First argument is not a buffer\n");\r
117     return NULL;\r
118   }\r
119 \r
120   // Because some Python objects which support "buffer" protocol have more than one\r
121   // memory segment, we have to copy them into a contiguous memory.\r
122   SrcBuf = malloc(SrcDataSize);\r
123   if (SrcBuf == NULL) {\r
124     PyErr_SetString(PyExc_Exception, "Not enough memory\n");\r
125     goto ERROR;\r
126   }\r
127 \r
128   SegNum = SrcData->ob_type->tp_as_buffer->bf_getsegcount((PyObject *)SrcData, NULL);\r
129   TmpBuf = SrcBuf;\r
130   for (Index = 0; Index < SegNum; ++Index) {\r
131     VOID *BufSeg;\r
132     Py_ssize_t Len;\r
133 \r
134     Len = SrcData->ob_type->tp_as_buffer->bf_getreadbuffer((PyObject *)SrcData, Index, &BufSeg);\r
135     if (Len < 0) {\r
136       PyErr_SetString(PyExc_Exception, "Buffer segment is not available\n");\r
137       goto ERROR;\r
138     }\r
139     memcpy(TmpBuf, BufSeg, Len);\r
140     TmpBuf += Len;\r
141   }\r
142 \r
143   Status = Extract((VOID *)SrcBuf, SrcDataSize, (VOID **)&DstBuf, &DstDataSize, 2);\r
144   if (Status != EFI_SUCCESS) {\r
145     PyErr_SetString(PyExc_Exception, "Failed to decompress\n");\r
146     goto ERROR;\r
147   }\r
148 \r
149   return PyString_FromStringAndSize((CONST INT8*)DstBuf, (Py_ssize_t)DstDataSize);\r
150 \r
151 ERROR:\r
152   if (SrcBuf != NULL) {\r
153     free(SrcBuf);\r
154   }\r
155 \r
156   if (DstBuf != NULL) {\r
157     free(DstBuf);\r
158   }\r
159   return NULL;\r
160 }\r
161 \r
162 \r
163 STATIC\r
164 PyObject*\r
165 UefiCompress(\r
166   PyObject    *Self,\r
167   PyObject    *Args\r
168   )\r
169 {\r
170   return NULL;\r
171 }\r
172 \r
173 \r
174 STATIC\r
175 PyObject*\r
176 FrameworkCompress(\r
177   PyObject    *Self,\r
178   PyObject    *Args\r
179   )\r
180 {\r
181   return NULL;\r
182 }\r
183 \r
184 STATIC INT8 DecompressDocs[] = "Decompress(): Decompress data using UEFI standard algorithm\n";\r
185 STATIC INT8 CompressDocs[] = "Compress(): Compress data using UEFI standard algorithm\n";\r
186 \r
187 STATIC PyMethodDef EfiCompressor_Funcs[] = {\r
188   {"UefiDecompress", (PyCFunction)UefiDecompress, METH_VARARGS, DecompressDocs},\r
189   {"UefiCompress", (PyCFunction)UefiCompress, METH_VARARGS, DecompressDocs},\r
190   {"FrameworkDecompress", (PyCFunction)FrameworkDecompress, METH_VARARGS, DecompressDocs},\r
191   {"FrameworkCompress", (PyCFunction)FrameworkCompress, METH_VARARGS, DecompressDocs},\r
192   {NULL, NULL, 0, NULL}\r
193 };\r
194 \r
195 PyMODINIT_FUNC\r
196 initEfiCompressor(VOID) {\r
197   Py_InitModule3("EfiCompressor", EfiCompressor_Funcs, "EFI Compression Algorithm Extension Module");\r
198 }\r
199 \r
200 \r