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