1 /*
2 * libtilemcore - Graphing calculator emulation library
3 *
4 * Copyright (C) 2009-2011 Benjamin Moody
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public License
8 * as published by the Free Software Foundation; either version 2.1 of
9 * the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, see
18 * <http://www.gnu.org/licenses/>.
19 */
20
21 #ifdef HAVE_CONFIG_H
22 # include <config.h>
23 #endif
24
25 #include <stdio.h>
26 #include <string.h>
27 #include "tilem.h"
28
certificate_valid(byte * cert)29 static int certificate_valid(byte* cert)
30 {
31 int i, n;
32
33 if (cert[0] != 0)
34 return 0;
35
36 i = 1;
37
38 /* check that the actual certificate area consists of valid
39 certificate fields */
40 while (cert[i] <= 0x0F) {
41 switch (cert[i + 1] & 0x0F) {
42 case 0x0D:
43 n = cert[i + 2] + 3;
44 break;
45 case 0x0E:
46 n = (cert[i + 2] << 8) + cert[i + 3] + 4;
47 break;
48 case 0x0F:
49 n = 6;
50 break;
51 default:
52 n = (cert[i + 1] & 0xf) + 2;
53 }
54 i += n;
55 if (i >= 0x2000)
56 return 0;
57 }
58
59 /* check that the fields end with FF */
60 if (cert[i] != 0xFF)
61 return 0;
62
63 /* if there are fields present, assume the certificate is OK */
64 if (i > 1)
65 return 1;
66
67 /* no fields present -> this could be an incompletely-patched
68 certificate from an older version of TilEm; verify that the
69 next 4k bytes are truly empty */
70 while (i < 0x1000) {
71 if (cert[i] != 0xFF)
72 return 0;
73 i++;
74 }
75
76 return 1;
77 }
78
tilem_calc_fix_certificate(TilemCalc * calc,byte * cert,int app_start,int app_end,unsigned exptab_offset)79 void tilem_calc_fix_certificate(TilemCalc* calc, byte* cert,
80 int app_start, int app_end,
81 unsigned exptab_offset)
82 {
83 int i, base, max_apps, page;
84 unsigned insttab_offset = 0x1fe0;
85
86 /* If the ROM was dumped from an unpatched OS, the certificate
87 needs to be patched for some calculator functions to
88 work. */
89
90 /* First, check if the certificate is already valid */
91
92 if (cert[0x2000] == 0)
93 base = 0x2000;
94 else
95 base = 0;
96
97 if (certificate_valid(cert + base)) {
98 return;
99 }
100
101 tilem_message(calc, "Repairing certificate area...");
102
103 memset(cert, 0xff, 16384);
104
105 cert[0] = 0;
106
107 cert[insttab_offset] = 0xfe;
108
109 if (app_start < app_end)
110 max_apps = app_end - app_start + 1;
111 else
112 max_apps = app_start - app_end + 1;
113
114 for (i = 0; i < max_apps; i++) {
115 if (app_start < app_end)
116 page = app_start + i;
117 else
118 page = app_start - i;
119
120 /* Clear installed bit / set expiration count for
121 existing apps. (If this incorrectly detects pages
122 that aren't really apps, don't worry about it;
123 better to err on the side of caution.) */
124 if (calc->mem[page << 14] != 0x80
125 || calc->mem[(page << 14) + 1] != 0x0f)
126 continue;
127
128 tilem_message(calc, "Found application at page %02x (index %d)",
129 page, i);
130
131 cert[insttab_offset + ((i + 1) / 8)] &= ~(1 << ((i + 1) % 8));
132
133 cert[exptab_offset + 2 * i] = 0x80;
134 cert[exptab_offset + 2 * i + 1] = 0x00;
135 }
136 }
137