Use git: path for pdclib
[fw/altos] / altoslib / AltosSelfFlash.java
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; version 2 of the License.
7  *
8  * This program is distributed in the hope that it will be useful, but
9  * WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11  * General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License along
14  * with this program; if not, write to the Free Software Foundation, Inc.,
15  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
16  */
17
18 package org.altusmetrum.altoslib_2;
19
20 import java.io.*;
21
22 public class AltosSelfFlash extends AltosProgrammer {
23         File                    file;
24         FileInputStream         input;
25         AltosHexfile            image;
26         AltosLink               link;
27         boolean                 aborted;
28         AltosFlashListener      listener;
29         AltosRomconfig          rom_config;
30
31         void action(String s, int percent) {
32                 if (listener != null && !aborted)
33                         listener.position(s, percent);
34         }
35
36         void action(int part, int total) {
37                 int percent = 100 * part / total;
38                 action(String.format("%d/%d (%d%%)",
39                                      part, total, percent),
40                        percent);
41         }
42
43         byte[] read_memory(long addr, int len) throws InterruptedException, IOException {
44                 int b;
45                 byte[]  data = new byte[len];
46
47                 for (int offset = 0; offset < len; offset += 0x100) {
48                         link.printf("R %x\n", addr + offset);
49                         byte[]  reply = link.get_binary_reply(5000, 0x100);
50                         
51                         if (reply == null)
52                                 throw new IOException("Read device memory timeout");
53                         for (b = 0; b < len; b++)
54                                 data[b+offset] = reply[b];
55                 }
56                 return data;
57         }
58                 
59         void write_memory(long addr, byte[] data, int start, int len) {
60                 int b;
61                 System.out.printf ("write_memory %x %d\n", addr, len);
62                 link.printf("W %x\n", addr);
63                 link.flush_output();
64                 for (b = 0; b < len; b++)
65                         link.putchar(data[start + b]);
66                 for (; b < 0x100; b++)
67                         link.putchar((byte) 0xff);
68         }
69
70         void reboot() {
71                 System.out.printf("reboot\n");
72                 link.printf("a\n");
73                 link.flush_output();
74         }
75
76         public void flash() {
77                 try {
78                         if (!check_rom_config())
79                                 throw new IOException("Invalid rom config settings");
80
81                         /*
82                          * Store desired config values into image
83                          */
84                         rom_config.write(image);
85
86                         int remain = image.data.length;
87                         long flash_addr = image.address;
88                         int image_start = 0;
89
90                         action("start", 0);
91                         action(0, image.data.length);
92                         while (remain > 0 && !aborted) {
93                                 int this_time = remain;
94                                 if (this_time > 0x100)
95                                         this_time = 0x100;
96
97                                 if (link != null) {
98                                         /* write the data */
99                                         write_memory(flash_addr, image.data, image_start, this_time);
100
101                                         byte[] check = read_memory(flash_addr, this_time);
102                                         for (int i = 0; i < this_time; i++)
103                                                 if (check[i] != image.data[image_start + i])
104                                                         throw new IOException(String.format("Flash write failed at 0x%x (%02x != %02x)",
105                                                                                             image.address + image_start + i,
106                                                                                             check[i], image.data[image_start + i]));
107                                 } else {
108                                         Thread.sleep(100);
109                                 }
110
111                                 remain -= this_time;
112                                 flash_addr += this_time;
113                                 image_start += this_time;
114
115                                 action(image.data.length - remain, image.data.length);
116                         }
117                         if (!aborted) {
118                                 System.out.printf ("done\n");
119                                 action("done", 100);
120                         }
121                         close();
122                 } catch (IOException ie) {
123                         action(ie.getMessage(), -1);
124                         abort();
125                 } catch (InterruptedException ie) {
126                         abort();
127                 }
128         }
129
130         public void close() {
131                 if (link != null) {
132                         reboot();
133                         try {
134                                 link.close();
135                         } catch (InterruptedException ie) {
136                         }
137                         link = null;
138                 }
139         }
140
141         synchronized public void abort() {
142                 aborted = true;
143                 close();
144         }
145
146         private AltosHexfile get_rom() throws InterruptedException {
147                 System.out.printf("get rom\n");
148                 try {
149                         int base = AltosRomconfig.fetch_base(image);
150                         int bounds = AltosRomconfig.fetch_bounds(image);
151                         byte[] data = read_memory(base, bounds - base);
152                         AltosHexfile hexfile = new AltosHexfile(data, base);
153                         hexfile.add_symbols(image);
154                         return hexfile;
155                 } catch (AltosNoSymbol none) {
156                         System.out.printf("no symbol %s\n", none.getMessage());
157                         return null;
158                 } catch (IOException ie) {
159                         return null;
160                 }
161
162         }
163
164         public boolean check_rom_config() throws InterruptedException {
165                 if (link == null) {
166                         System.out.printf ("no link\n");
167                         return true;
168                 }
169                 if (rom_config == null) {
170                         AltosHexfile hexfile = get_rom();
171                         if (hexfile != null)
172                                 rom_config = new AltosRomconfig(hexfile);
173                 }
174                 return rom_config != null && rom_config.valid();
175         }
176
177         public void set_romconfig (AltosRomconfig romconfig) {
178                 rom_config = romconfig;
179         }
180
181         public AltosRomconfig romconfig() throws InterruptedException {
182                 System.out.printf("fetch romconfig\n");
183                 if (!check_rom_config())
184                         return null;
185                 return rom_config;
186         }
187
188         public AltosSelfFlash(File file, AltosLink link, AltosFlashListener listener)
189                 throws IOException, FileNotFoundException, InterruptedException {
190                 this.file = file;
191                 this.link = link;
192                 this.listener = listener;
193                 input = new FileInputStream(file);
194                 image = new AltosHexfile(input);
195                 System.out.printf ("AltosSelfFlash %x\n", image.address);
196         }
197 }