altos/test: Adjust CRC error rate after FEC fix
[fw/altos] / ao-tools / lib / ao-editaltos.c
1 /*
2  * Copyright © 2013 Keith Packard <keithp@keithp.com>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License along
15  * with this program; if not, write to the Free Software Foundation, Inc.,
16  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
17  */
18
19 #include <string.h>
20 #include <stdlib.h>
21 #include "ao-editaltos.h"
22
23 struct ao_sym ao_symbols[] = {
24         [AO_ROMCONFIG_VERSION_INDEX] = {
25                 .name = "ao_romconfig_version",
26                 .required = 1
27         },
28         [AO_ROMCONFIG_CHECK_INDEX] = {
29                 .name = "ao_romconfig_check",
30                 .required = 1
31         },
32         [AO_SERIAL_NUMBER_INDEX] = {
33                 .name = "ao_serial_number",
34                 .required = 1
35         },
36         [AO_RADIO_CAL_INDEX] = {
37                 .name = "ao_radio_cal",
38                 .required = 0
39         },
40         [AO_USB_DESCRIPTORS_INDEX] = {
41                 .name = "ao_usb_descriptors",
42                 .required = 0
43         },
44 };
45
46 #define NUM_SYMBOLS             5
47
48 int ao_num_symbols = NUM_SYMBOLS;
49
50 /*
51  * Edit the to-be-written memory block
52  */
53 static bool
54 rewrite(struct ao_hex_image *load, unsigned address, uint8_t *data, int length)
55 {
56         if (address < load->address || load->address + load->length < address + length)
57                 return false;
58
59         memcpy(&load->data[address - load->address], data, length);
60         return true;
61 }
62
63 /*
64  * Find the symbols needed to correctly load the program
65  */
66
67 bool
68 ao_editaltos_find_symbols(struct ao_sym *file_symbols, int num_file_symbols,
69                           struct ao_sym *symbols, int num_symbols)
70 {
71         int     f, s;
72
73         for (f = 0; f < num_file_symbols; f++) {
74                 for (s = 0; s < num_symbols; s++) {
75                         if (strcmp(symbols[s].name, file_symbols[f].name) == 0) {
76                                 symbols[s].addr = file_symbols[f].addr;
77                                 symbols[s].found = true;
78                         }
79                 }
80         }
81         for (s = 0; s < num_symbols; s++)
82                 if (!symbols[s].found && symbols[s].required)
83                         return false;
84         return true;
85 }
86
87 bool
88 ao_editaltos(struct ao_hex_image *image,
89              uint16_t serial,
90              uint32_t cal)
91 {
92         uint8_t                 *serial_ucs2;
93         int                     serial_ucs2_len;
94         uint8_t                 serial_int[2];
95         unsigned int            s;
96         int                     i;
97         int                     string_num;
98         uint8_t                 cal_int[4];
99
100         /* Write the config values into the flash image
101          */
102
103         serial_int[0] = serial & 0xff;
104         serial_int[1] = (serial >> 8) & 0xff;
105
106         if (!rewrite(image, AO_SERIAL_NUMBER, serial_int, sizeof (serial_int))) {
107                 fprintf(stderr, "Cannot rewrite serial integer at %08x\n",
108                         AO_SERIAL_NUMBER);
109                 return false;
110         }
111
112         if (AO_USB_DESCRIPTORS) {
113                 uint32_t        usb_descriptors = AO_USB_DESCRIPTORS - image->address;
114                 string_num = 0;
115
116                 while (image->data[usb_descriptors] != 0 && usb_descriptors < image->length) {
117                         if (image->data[usb_descriptors+1] == AO_USB_DESC_STRING) {
118                                 ++string_num;
119                                 if (string_num == 4)
120                                         break;
121                         }
122                         usb_descriptors += image->data[usb_descriptors];
123                 }
124                 if (usb_descriptors >= image->length || image->data[usb_descriptors] == 0 ) {
125                         fprintf(stderr, "Cannot rewrite serial string at %08x\n", AO_USB_DESCRIPTORS);
126                         return false;
127                 }
128
129                 serial_ucs2_len = image->data[usb_descriptors] - 2;
130                 serial_ucs2 = malloc(serial_ucs2_len);
131                 if (!serial_ucs2) {
132                         fprintf(stderr, "Malloc(%d) failed\n", serial_ucs2_len);
133                         return false;
134                 }
135                 s = serial;
136                 for (i = serial_ucs2_len / 2; i; i--) {
137                         serial_ucs2[i * 2 - 1] = 0;
138                         serial_ucs2[i * 2 - 2] = (s % 10) + '0';
139                         s /= 10;
140                 }
141                 if (!rewrite(image, usb_descriptors + 2 + image->address, serial_ucs2, serial_ucs2_len)) {
142                         fprintf (stderr, "Cannot rewrite USB descriptor at %08x\n", AO_USB_DESCRIPTORS);
143                         return false;
144                 }
145         }
146
147         if (cal && AO_RADIO_CAL) {
148                 cal_int[0] = cal & 0xff;
149                 cal_int[1] = (cal >> 8) & 0xff;
150                 cal_int[2] = (cal >> 16) & 0xff;
151                 cal_int[3] = (cal >> 24) & 0xff;
152
153                 if (!rewrite(image, AO_RADIO_CAL, cal_int, sizeof (cal_int))) {
154                         fprintf(stderr, "Cannot rewrite radio calibration at %08x\n", AO_RADIO_CAL);
155                         return false;
156                 }
157         }
158         return true;
159 }
160
161 static uint16_t
162 read_le16(uint8_t *src)
163 {
164         return (uint16_t) src[0] | ((uint16_t) src[1] << 8);
165 }
166
167 bool
168 ao_heximage_usb_id(struct ao_hex_image *image, struct ao_usb_id *id)
169 {
170         uint32_t        usb_descriptors;
171
172         if (!AO_USB_DESCRIPTORS)
173                 return false;
174         usb_descriptors = AO_USB_DESCRIPTORS - image->address;
175
176         while (image->data[usb_descriptors] != 0 && usb_descriptors < image->length) {
177                 if (image->data[usb_descriptors+1] == AO_USB_DESC_DEVICE) {
178                         break;
179                 }
180                 usb_descriptors += image->data[usb_descriptors];
181         }
182
183         /*
184          * check to make sure there's at least 0x12 (size of a USB
185          * device descriptor) available
186          */
187         if (usb_descriptors >= image->length || image->data[usb_descriptors] != 0x12)
188                 return false;
189
190         id->vid = read_le16(image->data + usb_descriptors + 8);
191         id->pid = read_le16(image->data + usb_descriptors + 10);
192
193         return true;
194 }
195
196 uint16_t *
197 ao_heximage_usb_product(struct ao_hex_image *image)
198 {
199         uint32_t        usb_descriptors;
200         int             string_num;
201         uint16_t        *product;
202         uint8_t         product_len;
203
204         if (!AO_USB_DESCRIPTORS)
205                 return NULL;
206         usb_descriptors = AO_USB_DESCRIPTORS - image->address;
207
208         string_num = 0;
209         while (image->data[usb_descriptors] != 0 && usb_descriptors < image->length) {
210                 if (image->data[usb_descriptors+1] == AO_USB_DESC_STRING) {
211                         ++string_num;
212                         if (string_num == 3)
213                                 break;
214                 }
215                 usb_descriptors += image->data[usb_descriptors];
216         }
217
218         /*
219          * check to make sure there's at least 0x12 (size of a USB
220          * device descriptor) available
221          */
222         if (usb_descriptors >= image->length || image->data[usb_descriptors] == 0)
223                 return NULL;
224
225         product_len = image->data[usb_descriptors] - 2;
226
227         if (usb_descriptors < product_len + 2)
228                 return NULL;
229
230         product = malloc (product_len + 2);
231         if (!product)
232                 return NULL;
233
234         memcpy(product, image->data + usb_descriptors + 2, product_len);
235         product[product_len/2] = 0;
236         return product;
237 }