-
Notifications
You must be signed in to change notification settings - Fork 0
/
python_qdl.c
121 lines (103 loc) · 3.18 KB
/
python_qdl.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
#define PY_SSIZE_T_CLEAN
#include <Python.h>
#include "python_logging.h"
#include "qdl.h"
void progress_callback(void* context, int current, int total) {
if (!context) return;
end_allow_threads();
PyObject *py_callback = (PyObject *)context;
const PyObject* arglist = Py_BuildValue("(ii)", current, total);
PyEval_CallObject(py_callback, arglist);
begin_allow_threads();
}
// "%s [--debug] [--storage <emmc|ufs>] [--finalize-provisioning] [--include
// <PATH>] <prog.mbn> [<program> <patch> ...]\n",
//
// >>> qdl_run('emmc', mbn, prog, patch)
static PyObject *qdl_run(PyObject *self, PyObject *args) {
const char *storage;
const char *mbn;
const char *program;
const char *patch;
int type;
int ret;
struct qdl_device qdl;
PyObject *py_progress_callback;
if (!PyArg_ParseTuple(args, "ssssO", &storage, &mbn, &program, &patch, &py_progress_callback))
return NULL;
void* v_progress_callback = (void*) py_progress_callback;
begin_allow_threads();
type = detect_type(program);
end_allow_threads();
if (type != QDL_FILE_PROGRAM) {
PyErr_Format(PyExc_RuntimeError,
"Program passed is not a QDL program. Got type %d", type);
return NULL;
}
begin_allow_threads();
ret = program_load(program);
end_allow_threads();
if (ret < 0) {
PyErr_Format(PyExc_RuntimeError, "Program load failed. Error %d", ret);
return NULL;
}
begin_allow_threads();
type = detect_type(patch);
end_allow_threads();
if (type != QDL_FILE_PATCH) {
PyErr_Format(PyExc_RuntimeError,
"Patch passed is not a QDL patch. Got type %d", type);
return NULL;
}
begin_allow_threads();
ret = patch_load(patch);
end_allow_threads();
if (ret < 0) {
PyErr_Format(PyExc_RuntimeError, "Patch load failed. Error %d", ret);
return NULL;
}
begin_allow_threads();
ret = libusb_init(NULL);
end_allow_threads();
if (ret) {
PyErr_Format(PyExc_RuntimeError, "Could not load libusb. Error %d", ret);
return NULL;
}
begin_allow_threads();
ret = find_device(&qdl);
end_allow_threads();
if (ret) {
libusb_exit(NULL);
PyErr_Format(PyExc_RuntimeError, "Could not find device. Error %d", ret);
return NULL;
}
begin_allow_threads();
ret = sahara_run(&qdl, mbn);
end_allow_threads();
if (ret < 0) {
libusb_exit(NULL);
return Py_None;
PyErr_Format(PyExc_RuntimeError, "Could not run Sahara. Error %d\n", ret);
return NULL;
}
begin_allow_threads();
ret = firehose_run(&qdl, NULL, storage, v_progress_callback);
end_allow_threads();
if (ret < 0) {
libusb_exit(NULL);
PyErr_Format(PyExc_RuntimeError, "Could not run Firehose. Error %d\n", ret);
return NULL;
}
return Py_None;
}
static PyMethodDef QdlMethods[] = {
{"run", qdl_run, METH_VARARGS, "Runs QDL"},
{NULL, NULL, 0, NULL} /* Sentinel */
};
static struct PyModuleDef QdlModule = {
PyModuleDef_HEAD_INIT, "qdl", /* name of module */
NULL, /* module documentation, may be NULL */
-1, /* size of per-interpreter state of the module,
or -1 if the module keeps state in global variables. */
QdlMethods};
PyMODINIT_FUNC PyInit_qdl(void) { return PyModule_Create(&QdlModule); }