summaryrefslogtreecommitdiff
path: root/other/Kermit/lib/Patch.cpp
diff options
context:
space:
mode:
authorRoot THC2026-02-24 12:42:47 +0000
committerRoot THC2026-02-24 12:42:47 +0000
commitc9cbeced5b3f2bdd7407e29c0811e65954132540 (patch)
treeaefc355416b561111819de159ccbd86c3004cf88 /other/Kermit/lib/Patch.cpp
parent073fe4bf9fca6bf40cef2886d75df832ef4b6fca (diff)
initial
Diffstat (limited to 'other/Kermit/lib/Patch.cpp')
-rw-r--r--other/Kermit/lib/Patch.cpp502
1 files changed, 502 insertions, 0 deletions
diff --git a/other/Kermit/lib/Patch.cpp b/other/Kermit/lib/Patch.cpp
new file mode 100644
index 0000000..b72f860
--- /dev/null
+++ b/other/Kermit/lib/Patch.cpp
@@ -0,0 +1,502 @@
1/*
2 * Patch.cpp:
3 * written by palmers / teso
4 */
5#include <Patch.hpp>
6
7SystemMap DummyValMap;
8
9/*
10 * helper class
11 */
12class replaceAddr
13{
14private:
15 unsigned char *data;
16 unsigned short len;
17
18public:
19 replaceAddr (unsigned char *a, unsigned short x)
20 {
21 data = a;
22 len = x;
23 }
24
25 void operator() (Addr2Addr *a)
26 {
27 unsigned short x = 0;
28 unsigned char *b = NULL,
29 *c = NULL;
30
31 b = (unsigned char *) &a->first;
32 c = (unsigned char *) &a->second;
33
34 for (x = 0; x <= (len - 3); x++)
35 {
36 if (b[0] == data[x])
37 {
38 if ((b[1] == data[x + 1]) && \
39 (b[2] == data[x + 2]) && \
40 (b[3] == data[x + 3]))
41 {
42 data[x] = c[0];
43 data[x + 1] = c[1];
44 data[x + 2] = c[2];
45 data[x + 3] = c[3];
46 }
47 }
48 }
49 }
50};
51
52
53/*
54 * member functions
55 */
56 string Patch::state2string ()
57 {
58 string ret;
59
60 switch (state)
61 {
62 case CLEAN:
63 ret = "Clean";
64 break;
65 case LINKED:
66 ret = "Linked";
67 break;
68 case APPLIED:
69 ret = "Applied";
70 break;
71 case AFAILED:
72 ret = "ApplyFailed";
73 break;
74 case LFAILED:
75 ret = "LinkFailed";
76 break;
77 default:
78 ret = "Unknown";
79 break;
80 }
81 return ret;
82 }
83
84
85 void Patch::string2state (string a)
86 {
87 if (a == "Clean")
88 state = CLEAN;
89 else if (a == "Linked")
90 state = LINKED;
91 else if (a == "Applied")
92 state = APPLIED;
93 else if (a == "ApplyFailed")
94 state = AFAILED;
95 else if (a == "LinkFailed")
96 state = LFAILED;
97 else if (a == "Unknown")
98 abort ();
99 }
100
101
102 string Patch::data2string (unsigned char *a)
103 {
104 string ret;
105 int x;
106
107 ret = itos16 ((unsigned int) a[0]);
108 for (x = 1; x < len; x++)
109 {
110 ret += ' ';
111 ret += itos16 ((unsigned int) a[x]);
112 }
113
114 return ret;
115 }
116
117
118 void Patch::string2data (string s, unsigned char *d)
119 {
120 string tmp;
121 unsigned short x,
122 y;
123
124 for (x = 0; x < (len - 1); x++)
125 {
126 y = s.find_first_of (" ");
127 tmp.resize (y);
128 s.copy (tmp.begin (), y);
129 s.erase (0, y + 1);
130 d[x] = (unsigned char) stoi16 (tmp) & 0xff;
131 tmp.erase ();
132 }
133 tmp.resize (s.length ());
134 s.copy (tmp.begin (), s.length ());
135 d[x] = (unsigned char) stoi16 (tmp) & 0xff;
136 }
137
138
139 bool Patch::initObjects (unsigned char *d, unsigned short l, unsigned int add, rwKernel *x)
140 {
141 len = l;
142 address = add;
143 local_rw = x;
144
145 data = new unsigned char[len];
146 back_data = new unsigned char[len];
147 overwr = new unsigned char[len];
148
149 copy (d, d + len, data);
150 copy (d, d + len, back_data);
151 state = CLEAN;
152 return true;
153 }
154
155
156 void Patch::parse (string s)
157 {
158 unsigned char *a = NULL;
159 string tmp;
160 int x = 0;
161
162 x = s.find_first_of (",");
163 tmp.resize (x);
164 s.copy (tmp.begin (), x);
165 s.erase (0, x + 1);
166
167 address = stoi16 (tmp);
168 tmp.erase ();
169
170 x = s.find_first_of (":");
171 tmp.resize (x);
172 s.copy (tmp.begin (), x);
173 s.erase (0, x + 1);
174
175 string2state (tmp);
176 tmp.erase ();
177
178 x = s.find_first_of ("(");
179 s.erase (0, x + 1);
180
181 x = s.find_first_of (")");
182 tmp.resize (x);
183 s.copy (tmp.begin (), x);
184 len = count (tmp.begin (), tmp.end (), ' ') + 1;
185
186 data = new unsigned char[len];
187 back_data = new unsigned char[len];
188 overwr = new unsigned char[len];
189
190 string2data (tmp, data);
191 tmp.erase ();
192
193 if (state == CLEAN)
194 return;
195
196 switch (state)
197 {
198 case LINKED:
199 case LFAILED:
200 a = back_data;
201 break;
202 case APPLIED:
203 case AFAILED:
204 a = overwr;
205 break;
206 }
207
208 x = s.find_first_of ("(");
209 s.erase (0, x + 1);
210
211 x = s.find_first_of (")");
212 tmp.resize (x);
213 s.copy (tmp.begin (), x);
214
215 string2data (tmp, a);
216 }
217
218
219 Patch::Patch ()
220 {
221 }
222
223
224 Patch::Patch (unsigned char *d, unsigned short l, unsigned int add)
225 {
226 initObjects (d, l, add, NULL);
227 }
228
229
230 Patch::Patch (unsigned char *d, unsigned short l, unsigned int add, rwKernel *x)
231 {
232 initObjects (d, l, add, x);
233 }
234
235
236 Patch::Patch (string s)
237 {
238 parse (s);
239 }
240
241
242 Patch::Patch (string s, rwKernel *rw)
243 {
244 parse (s);
245 local_rw = rw;
246 }
247
248
249 Patch::~Patch ()
250 {
251 delete data;
252 delete back_data;
253 delete overwr;
254 }
255
256
257 void Patch::initFromString (string a)
258 {
259 parse (a);
260 }
261
262
263 string Patch::getPatchAsString ()
264 {
265 unsigned char *a = NULL;
266 string b;
267
268 switch (state)
269 {
270 case LINKED:
271 case LFAILED:
272 a = back_data;
273 break;
274 case APPLIED:
275 case AFAILED:
276 a = overwr;
277 break;
278 }
279
280 b = itos16 (address) + ',' + state2string () + ": (" + data2string (data) + ')';
281 if (a != NULL)
282 b += ", (" + data2string (a) + ')';
283 b += '\n';
284 return b;
285 }
286
287
288 bool Patch::isLinked ()
289 {
290 return (state & LINKED);
291 }
292
293
294 bool Patch::wasChanged ()
295 {
296 int x;
297
298 for (x = 0; x < len; x++)
299 if (data[x] != back_data[x])
300 return true;
301 return false;
302 }
303
304
305 bool Patch::isApplied ()
306 {
307 return (state & APPLIED);
308 }
309
310
311 bool Patch::isClean ()
312 {
313 return (state & CLEAN);
314 }
315
316
317 bool Patch::isFailed ()
318 {
319 return (state & AFAILED) || (state & LFAILED);
320 }
321
322
323 int Patch::getState ()
324 {
325 return state;
326 }
327
328
329 void Patch::restore ()
330 {
331 copy (back_data, back_data + len, data);
332 state = CLEAN;
333 }
334
335
336 bool Patch::remove (rwKernel *rw)
337 {
338 if (state != APPLIED)
339 return false;
340
341 rw->write (overwr, len, address);
342 return true;
343 }
344
345
346 bool Patch::remove ()
347 {
348 if (local_rw == NULL)
349 return false;
350 if (state != APPLIED)
351 return false;
352
353 local_rw->write (overwr, len, address);
354 return true;
355 }
356
357
358 unsigned char *Patch::getData ()
359 {
360 return data;
361 }
362
363
364 void Patch::apply (rwKernel *rw)
365 {
366/* pretty simple :) */
367 rw->read (overwr, len, address);
368 rw->write (data, len, address);
369 state = APPLIED;
370 }
371
372
373 void Patch::apply ()
374 {
375 if (local_rw == NULL)
376 {
377 state = AFAILED;
378 return;
379 }
380 local_rw->read (overwr, len, address);
381 local_rw->write (data, len, address);
382 state = APPLIED;
383 }
384
385
386 void Patch::link (Addr2AddrList *a2a)
387 {
388 replaceAddr x (data, len);
389 int y = a2a->size ();
390 Addr2AddrList::iterator z = a2a->begin ();
391 Addr2Addr *t = NULL;
392
393/* XXX: why doesnt for_each work with pointer to list???
394 * its the same problem with for "(x = a2a->begin (); x != a2a->end (); ..."
395 * the x != end (); just f#$§ true!
396 */
397 while (y--)
398 {
399 t = *z;
400 x (t);
401 z++;
402 }
403 state = LINKED;
404 }
405
406
407 void Patch::dump (string file)
408 {
409 unsigned char *a = NULL;
410/*
411 * dump file format:
412 * <Address>,<State>: (<data, hex, byte wise>){, (<other data, hex, byte wise>)}\n
413 * where the data in the curled brackets in depending on the state:
414 * state: data in the curled bbrackets:
415 * clean none
416 * applied overwr
417 * afailed overwr
418 * linked back_date
419 * lfailed back_data
420 */
421 ofstream f;
422
423 switch (state)
424 {
425 case LINKED:
426 case LFAILED:
427 a = back_data;
428 break;
429 case APPLIED:
430 case AFAILED:
431 a = overwr;
432 break;
433 }
434
435 f.open (file.c_str (), ios::ate | ios::app);
436
437 f.setf (ios::hex, ios::basefield);
438 f << address << ',' << state2string () << ':' << ' ';
439 f << '(' << data2string (data) << ')';
440 if (a != NULL)
441 f << ',' << ' ' << '(' << data2string (a) << ')';
442 f << endl;
443 f.setf (ios::dec, ios::basefield);
444 }
445
446
447 istream& operator>> (istream& is, Patch& p)
448 {
449 string tmp;
450
451 getline (is, tmp, '\n');
452 p.initFromString (tmp);
453 return is;
454 }
455
456
457 ostream& operator<< (ostream& os, Patch& p)
458 {
459 os << p.getPatchAsString ();
460 return os;
461 }
462
463
464/*
465 * unrelated functions ....
466 */
467 Addr2AddrList *genReplaceValMap (SymbolTable *st)
468 {
469 zzSymList::iterator x;
470 Addr2Addr *y = NULL;
471 zzSym *z = NULL;
472 Addr2AddrList *a2a = NULL;
473
474 a2a = new Addr2AddrList ();
475
476 /* get all symbol addressess together with dummy values */
477 for (x = st->symList.begin (); x != st->symList.end (); x++)
478 {
479 z = *x;
480 if (DummyValMap[z->Name] != 0)
481 {
482 y = new Addr2Addr ();
483 y->first = DummyValMap[z->Name];
484 y->second = z->Address;
485 a2a->push_back (y);
486 }
487 }
488 return a2a;
489 }
490
491
492 void genDummyValMap ()
493 {
494 int x = 0;
495
496 while (__n2a[x].name != NULL)
497 {
498 DummyValMap.add (string (__n2a[x].name), __n2a[x].add);
499 x++;
500 }
501 }
502