make simtest compile, probably breaking calypso_sim_init
[osmocom-bb.git] / src / target / firmware / apps / simtest / main.c
1 /* SIM test application */
2
3 /* (C) 2010 by Harald Welte <laforge@gnumonks.org>
4  *
5  * All Rights Reserved
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License along
18  * with this program; if not, write to the Free Software Foundation, Inc.,
19  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  */
22
23 #include <stdint.h>
24 #include <stdio.h>
25 #include <string.h>
26
27 #include <debug.h>
28 #include <memory.h>
29 #include <delay.h>
30 #include <rffe.h>
31 #include <keypad.h>
32 #include <board.h>
33 #include <abb/twl3025.h>
34 #include <display.h>
35 #include <rf/trf6151.h>
36 #include <calypso/clock.h>
37 #include <calypso/tpu.h>
38 #include <calypso/tsp.h>
39 #include <calypso/dsp.h>
40 #include <calypso/irq.h>
41 #include <calypso/misc.h>
42 #include <comm/sercomm.h>
43 #include <comm/timer.h>
44
45 #include <calypso/sim.h>
46
47 #define DEBUG
48
49 /* Dump bytes in hex on the console */
50 static void myHexdump(uint8_t *data, int len)
51 {
52         int i;
53
54         for(i=0;i<len;i++)
55                 printf("%02x ",data[i]);
56
57         printf("(%i bytes)\n", len);
58
59         return;
60 }
61
62 /* SIM instructions
63    All instructions a standard sim card must feature: */
64 #define SIM_CLASS 0xA0                  /* Class that contains the following instructions */
65 #define SIM_SELECT 0xA4                 /* Select a file on the card */
66 #define SIM_STATUS 0xF2                 /* Get the status of the currently selected file */
67 #define SIM_READ_BINARY 0xB0            /* Read file in binary mode */
68 #define SIM_UPDATE_BINARY 0xD6          /* Write file in binary mode */
69 #define SIM_READ_RECORD 0xB2            /* Read record of a record based file */
70 #define SIM_UPDATE_RECORD 0xDC          /* Write record of a record based file */
71 #define SIM_SEEK 0xA2                   /* Seek in a record based file */
72 #define SIM_INCREASE 0x32               /* Increase a record in a record based file */
73 #define SIM_VERIFY_CHV 0x20             /* Authenticate with card (enter pin) */
74 #define SIM_CHANGE_CHV 0x24             /* Change pin */
75 #define SIM_DISABLE_CHV 0x26            /* Disable pin so that no authentication is needed anymore */
76 #define SIM_ENABLE_CHV 0x28             /* Enable pin, authentication is now needed again */
77 #define SIM_UNBLOCK_CHV 0x2C            /* Unblock pin when it is blocked by entering a wrong pin three times */
78 #define SIM_INVALIDATE 0x04             /* Invalidate the current elementry file (file in a subdirectory) */
79 #define SIM_REHABILITATE 0x44           /* Rehabilitate the current elementry file (file in a subdirectory) */
80 #define SIM_RUN_GSM_ALGORITHM 0x88      /* Run the GSM A3 authentication algorithm in the card */
81 #define SIM_SLEEP 0xFA                  /* Sleep command (only used in Phase 1 GSM) */
82 #define SIM_GET_RESPONSE 0xC0           /* Get the response of a command from the card */
83
84 /* File identifiers (filenames)
85    The file identifiers are the standardized file identifiers mentioned in the
86    GSM-11-11 specification. */
87 #define SIM_MF          0x3F00
88 #define SIM_EF_ICCID    0x2FE2
89 #define SIM_DF_TELECOM  0x7F10
90 #define SIM_EF_ADN      0x6F3A
91 #define SIM_EF_FDN      0x6F3B
92 #define SIM_EF_SMS      0x6F3C
93 #define SIM_EF_CCP      0x6F3D
94 #define SIM_EF_MSISDN   0x6F40
95 #define SIM_EF_SMSP     0x6F42
96 #define SIM_EF_SMSS     0x6F43
97 #define SIM_EF_LND      0x6F44
98 #define SIM_EF_EXT1     0x6F4A
99 #define SIM_EF_EXT2     0x6F4B
100 #define SIM_DF_GSM      0x7F20
101 #define SIM_EF_LP       0x6F05
102 #define SIM_EF_IMSI     0x6F07
103 #define SIM_EF_KC       0x6F20
104 #define SIM_EF_PLMNsel  0x6F30
105 #define SIM_EF_HPLMN    0x6F31
106 #define SIM_EF_ACMmax   0x6F37
107 #define SIM_EF_SST      0x6F38
108 #define SIM_EF_ACM      0x6F39
109 #define SIM_EF_GID1     0x6F3E
110 #define SIM_EF_GID2     0x6F3F
111 #define SIM_EF_PUCT     0x6F41
112 #define SIM_EF_CBMI     0x6F45
113 #define SIM_EF_SPN      0x6F46
114 #define SIM_EF_BCCH     0x6F74
115 #define SIM_EF_ACC      0x6F78
116 #define SIM_EF_FPLMN    0x6F7B
117 #define SIM_EF_LOCI     0x6F7E
118 #define SIM_EF_AD       0x6FAD
119 #define SIM_EF_PHASE    0x6FAE
120
121 /* Select a file on the card */
122 uint16_t sim_select(uint16_t fid)
123 {
124         uint8_t txBuffer[2];
125         uint8_t status_word[2];
126
127         txBuffer[1] = (uint8_t) fid;
128         txBuffer[0] = (uint8_t) (fid >> 8);
129
130         if(calypso_sim_transceive(SIM_CLASS, SIM_SELECT, 0x00, 0x00, 0x02,
131                                   txBuffer, status_word, SIM_APDU_PUT) != 0)
132                 return 0xFFFF;
133
134         return (status_word[0] << 8) | status_word[1];
135 }
136
137 /* Get the status of the currently selected file */
138 uint16_t sim_status(void)
139 {
140         uint8_t status_word[2];
141
142         if(calypso_sim_transceive(SIM_CLASS, SIM_STATUS, 0x00, 0x00, 0x00, 0,
143                                   status_word, SIM_APDU_PUT) != 0)
144                 return 0xFFFF;
145
146         return (status_word[0] << 8) | status_word[1];
147 }
148
149 /* Read file in binary mode */
150 uint16_t sim_readbinary(uint8_t offset_high, uint8_t offset_low, uint8_t length, uint8_t *data)
151 {
152         uint8_t status_word[2];
153         if(calypso_sim_transceive(SIM_CLASS, SIM_READ_BINARY, offset_high,
154                                   offset_low, length, data ,status_word,
155                                   SIM_APDU_GET) != 0)
156                 return 0xFFFF;
157
158         return (status_word[0] << 8) | status_word[1];
159 }
160
161 uint16_t sim_verify(char *pin)
162 {
163         uint8_t txBuffer[8];
164         uint8_t status_word[2];
165
166         memset(txBuffer, 0xFF, 8);
167         memcpy(txBuffer, pin, strlen(pin));
168
169         if(calypso_sim_transceive(SIM_CLASS, SIM_VERIFY_CHV, 0x00, 0x01, 0x08, txBuffer,status_word, SIM_APDU_PUT) != 0)
170                 return 0xFFFF;
171
172         return (status_word[0] << 8) | status_word[1];
173 }
174
175 uint16_t sim_run_gsm_algorith(uint8_t *data)
176 {
177         uint8_t status_word[2];
178
179         if(calypso_sim_transceive(SIM_CLASS, SIM_RUN_GSM_ALGORITHM, 0x00, 0x00, 0x10, data, status_word, SIM_APDU_PUT) != 0)
180                 return 0xFFFF;
181
182         printf("   ==> Status word: %x\n", (status_word[0] << 8) | status_word[1]);
183
184         if(status_word[0] != 0x9F || status_word[1] != 0x0C)
185                 return (status_word[0] << 8) | status_word[1];
186
187         /* GET RESPONSE */
188
189         if(calypso_sim_transceive(SIM_CLASS, SIM_GET_RESPONSE, 0, 0, 0x0C, data ,status_word, SIM_APDU_GET) != 0)
190                 return 0xFFFF;
191
192         return (status_word[0] << 8) | status_word[1];
193 }
194
195
196 /* FIXME: We need proper calibrated delay loops at some point! */
197 void delay_us(unsigned int us)
198 {
199         volatile unsigned int i;
200
201         for (i= 0; i < us*4; i++) { i; }
202 }
203
204 void delay_ms(unsigned int ms)
205 {
206         volatile unsigned int i;
207         for (i= 0; i < ms*1300; i++) { i; }
208 }
209
210
211
212
213 /* Execute my (dexter's) personal test */
214 void do_sim_test(void)
215 {
216         uint8_t testBuffer[20];
217         uint8_t testtxBuffer[20];
218
219         uint8_t testDataBody[257];
220         uint8_t testStatusWord[2];
221         int recivedChars;
222         int i;
223
224         uint8_t atr[20];
225         uint8_t atrLength = 0;
226
227         memset(atr,0,sizeof(atr));
228
229
230
231         uint8_t buffer[20];
232
233
234         memset(testtxBuffer,0,sizeof(testtxBuffer));
235
236         puts("----------------SIMTEST----8<-----------------\n");
237
238         /* Initialize Sim-Controller driver */
239         puts("Initializing driver:\n");
240         calypso_sim_init(NULL);
241
242         /* Power up sim and display ATR */
243         puts("Power up simcard:\n");
244         memset(atr,0,sizeof(atr));
245         atrLength = calypso_sim_powerup(atr);
246         myHexdump(atr,atrLength);
247
248         /* Reset sim and display ATR */
249         puts("Reset simcard:\n");
250         memset(atr,0,sizeof(atr));
251         atrLength = calypso_sim_reset(atr);
252         myHexdump(atr,atrLength);
253
254
255
256         testDataBody[0] = 0x3F;
257         testDataBody[1] = 0x00;
258         calypso_sim_transceive(0xA0, 0xA4, 0x00, 0x00, 0x02, testDataBody,0, SIM_APDU_PUT);
259         calypso_sim_transceive(0xA0, 0xC0, 0x00, 0x00, 0x0f, testDataBody,0, SIM_APDU_GET);
260         myHexdump(testDataBody,0x0F);
261
262         puts("Test Phase 1: Testing bare sim commands...\n");
263
264         puts(" * Testing SELECT: Selecting MF\n");
265         printf("   ==> Status word: %x\n", sim_select(SIM_MF));
266
267         puts(" * Testing SELECT: Selecting DF_GSM\n");
268         printf("   ==> Status word: %x\n", sim_select(SIM_DF_GSM));
269
270         puts(" * Testing PIN VERIFY\n");
271         printf("   ==> Status word: %x\n", sim_verify("1234"));
272
273         puts(" * Testing SELECT: Selecting EF_IMSI\n");
274         printf("   ==> Status word: %x\n", sim_select(SIM_EF_IMSI));
275
276         puts(" * Testing STATUS:\n");
277         printf("   ==> Status word: %x\n", sim_status());
278
279         memset(buffer,0,sizeof(buffer));
280         puts(" * Testing READ BINARY:\n");
281         printf("   ==> Status word: %x\n", sim_readbinary(0,0,9,buffer));
282         printf("       Data: ");
283         myHexdump(buffer,9);
284
285         memset(buffer,0,sizeof(buffer));
286         memcpy(buffer,"\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xaa\xbb\xcc\xdd\xee\xff",16);
287         puts(" * Testing RUN GSM ALGORITHM\n");
288         printf("   ==> Status word: %x\n", sim_run_gsm_algorith(buffer));
289         printf("       Result: ");
290         myHexdump(buffer,12);
291
292         delay_ms(5000);
293
294         calypso_sim_powerdown();
295
296         puts("------------END SIMTEST----8<-----------------\n");
297 }
298
299 /* Main Program */
300 const char *hr = "======================================================================\n";
301
302 void key_handler(enum key_codes code, enum key_states state);
303
304 static void *console_rx_cb(uint8_t dlci, struct msgb *msg)
305 {
306         if (dlci != SC_DLCI_CONSOLE) {
307                 printf("Message for unknown DLCI %u\n", dlci);
308                 return;
309         }
310
311         printf("Message on console DLCI: '%s'\n", msg->data);
312         msgb_free(msg);
313 }
314
315 int main(void)
316 {
317         board_init();
318
319         puts("\n\nOSMOCOM SIM Test (revision " GIT_REVISION ")\n");
320         puts(hr);
321
322         /* Dump device identification */
323         dump_dev_id();
324         puts(hr);
325
326         /* Dump clock config before PLL set */
327         calypso_clk_dump();
328         puts(hr);
329
330         keypad_set_handler(&key_handler);
331
332         /* Dump clock config after PLL set */
333         calypso_clk_dump();
334         puts(hr);
335
336         /* Dump all memory */
337         //dump_mem();
338 #if 0
339         /* Dump Bootloader */
340         memdump_range((void *)0x00000000, 0x2000);
341         puts(hr);
342 #endif
343
344         display_set_attr(DISP_ATTR_INVERT);
345         display_puts("SIM-TEST");
346
347         sercomm_register_rx_cb(SC_DLCI_CONSOLE, console_rx_cb);
348
349         do_sim_test();
350
351         /* beyond this point we only react to interrupts */
352         puts("entering interrupt loop\n");
353         while (1) {
354         }
355
356         twl3025_power_off();
357         while (1) {}
358 }
359
360 void key_handler(enum key_codes code, enum key_states state)
361 {
362         if (state != PRESSED)
363                 return;
364
365         switch (code) {
366         default:
367                 break;
368         }
369 }