1 #include <libfb/fb_lib.h>
2
3 #if defined(STDC_HEADERS) || defined(HAVE_STDLIB_H)
4 # include <stdlib.h>
5 #endif
6
7 /**
8 * @file flash.c
9 *
10 * @brief Flash block manipulation commands
11 *
12 * Functions not prefixed with udp_* use raw Ethernet communication
13 * and should not be used for new applications except when needed for
14 * device bring-up.
15 *
16 */
17
18 /** @brief Read from flash memory via UDP
19 *
20 * @param f the device context
21 * @param address the block number (not address) to read
22 * @param len the number of bytes (8-bit words) to read
23 * @param buffer location of at least length, len + sizeof(DOOF_BLK),
24 * to store the read bytes. A DOOF_BLK header is appended in front of
25 * the actual bytes read from flash.
26 * @return an error code, if applicable
27 */
28 fblib_err
udp_read_blk(libfb_t * f,uint32_t address,uint16_t len,uint8_t * buffer)29 udp_read_blk (libfb_t * f, uint32_t address, uint16_t len, uint8_t * buffer)
30 {
31 fblib_err err;
32 DOOF_BLK pkt;
33 uint8_t *localbuf;
34
35 localbuf = malloc (sizeof (DOOF_BLK) + len);
36 if (localbuf == NULL)
37 {
38 return FBLIB_EERRNO;
39 }
40 pkt.addr = address;
41 pkt.len = len;
42
43 err = custom_cmd_reply (f, DOOF_CMD_READ_BLK, 0, (char *) &pkt,
44 sizeof (DOOF_BLK), (char *) localbuf,
45 len + sizeof (DOOF_BLK));
46
47 memcpy (buffer, localbuf + sizeof (DOOF_BLK), len);
48
49 free (localbuf);
50
51 return err;
52 }
53
54 /** @brief Load a buffer into a device and prepare it for writing to flash.
55 *
56 * This function merely loads the desired buffer onto the device. You
57 * must finish the transaction by calling udp_start_blk_write() on the
58 * same address.
59 *
60 * Only one flash block can be written at a time. The address
61 * represents a relative address in that block, i.e. from
62 * [0..EPCS_BLK_SIZE). Writes must be small, as they are limited to
63 * the maximum UDP/Ethernet packet size. Once all bytes have been
64 * written they must be commited to flash with udp_start_blk_write().
65 *
66 * @brief f the device context
67 * @brief address the relative address in a block, i.e. in the set
68 * [0..EPCS_BLK_SIZE).
69 * @brief len the number of bytes to write
70 * @brief buffer a buffer of at least length len containing the data to write
71 * @return an error code if applicable
72 */
73 fblib_err
udp_write_to_blk(libfb_t * f,uint32_t address,uint16_t len,uint8_t * buffer)74 udp_write_to_blk (libfb_t * f, uint32_t address, uint16_t len,
75 uint8_t * buffer)
76 {
77 fblib_err err;
78
79 uint8_t *vbuf;
80 uint8_t *payload;
81 DOOF_BLK *pkt;
82
83 vbuf = malloc (len + sizeof (DOOF_BLK));
84 if (!vbuf)
85 return FBLIB_EERRNO;
86
87 // Build DOOF_BLK in memory
88 pkt = (DOOF_BLK *) vbuf;
89 pkt->addr = address;
90 pkt->len = len;
91
92 // Point to location of payload data and copy that data in
93 payload = vbuf + sizeof (DOOF_BLK);
94 memcpy (payload, buffer, len);
95
96 err =
97 custom_cmd_reply (f, DOOF_CMD_WRITE_BLK, 0, (char *) vbuf,
98 len + sizeof (DOOF_BLK), NULL, 0);
99 free (vbuf);
100 return err;
101 }
102
103 /** @brief Commit a write into flash memory
104 *
105 * @param f the device context
106 * @param address the flash block number (not the address)
107 * @return an error code if applicable
108 */
109 fblib_err
udp_start_blk_write(libfb_t * f,uint32_t blk)110 udp_start_blk_write (libfb_t * f, uint32_t blk)
111 {
112 fblib_err err;
113 DOOF_BLK pkt;
114 pkt.addr = blk;
115 pkt.len = 0;
116
117 err =
118 custom_cmd_reply (f, DOOF_CMD_START_WRITE, 0, (char *) &pkt,
119 sizeof (DOOF_BLK), NULL, 0);
120 return err;
121 }
122
123
124 /** @brief Prepare a write to a flash block
125 *
126 * Length in BLK commands refers to payload length only (ie: length to
127 * read/write), not complete packet length. Buffer should point to
128 * start of payload, not packet.
129 *
130 * @param f the device context
131 * @param dest_mac destination MAC address
132 * @param address flash block number to write to
133 * @param length see above
134 * @param buffer payload memory location
135 * @return A negative value if failure detected
136 */
137 int
write_to_blk(libfb_t * f,unsigned char * dest_mac,int address,int length,unsigned char * buffer)138 write_to_blk (libfb_t * f, unsigned char *dest_mac, int address, int length,
139 unsigned char *buffer)
140 {
141 DOOF_BLK *packet = malloc (sizeof (DOOF_BLK) + length);
142 int res, len = 0;
143 void *vptr = (void *) packet;
144
145 unsigned char recv_buf[1500];
146
147 if (length > 256)
148 return FBLIB_EINVAL;
149
150 memset ((void *) packet, 0, sizeof (DOOF_BLK) + length);
151
152 packet->addr = address;
153 packet->len = length;
154
155 /* The length of the payload to the 0xD00f packet will be the BLK HEADER plus the payload */
156 len = sizeof (DOOF_BLK) + length;
157
158 vptr += sizeof (DOOF_BLK);
159
160 memcpy (vptr, buffer, length);
161
162 res =
163 doof_txrx (f, dest_mac, (unsigned char *) packet, DOOF_CMD_WRITE_BLK, 0,
164 len, recv_buf);
165 free ((void *) packet);
166 return res;
167
168 }
169
170 /** @brief Initiate the write process into flash
171 *
172 * Flash writing is transactional. write_to_blk must first be called to load the payload.
173 *
174 * @param f the device context
175 * @param dest_mac destination MAC address
176 * @param address flash block number to write to
177 * @return 0 on success
178 */
179 int
start_blk_write(libfb_t * f,unsigned char * dest_mac,int address)180 start_blk_write (libfb_t * f, unsigned char *dest_mac, int address)
181 {
182 DOOF_BLK *packet = malloc (sizeof (DOOF_BLK));
183 int res, len = 0;
184 unsigned char recv_buf[1500];
185
186 memset ((void *) packet, 0, sizeof (DOOF_BLK));
187
188 packet->addr = address;
189
190 len = sizeof (DOOF_BLK);
191
192
193 res =
194 doof_txrx (f, dest_mac, (unsigned char *) packet, DOOF_CMD_START_WRITE, 0,
195 len, recv_buf);
196
197 free ((void *) packet);
198 return res;
199 }
200
201 /** @brief Read 'length' bytes into buffer from address in flash
202 *
203 * @param f the device context
204 * @param dest_mac destination MAC address
205 * @param address flash block number to read from
206 * @param length number of bytes to read
207 * @param recv_buf memory location to store received payload
208 */
209 int
read_blk(libfb_t * f,unsigned char * dest_mac,int address,int length,unsigned char * recv_buf)210 read_blk (libfb_t * f, unsigned char *dest_mac, int address, int length,
211 unsigned char *recv_buf)
212 {
213 DOOF_BLK *packet = (DOOF_BLK *) malloc (sizeof (DOOF_BLK));
214 unsigned char buf[1500];
215
216 int res, len = 0;
217
218 if (length > 256)
219 return -FBLIB_EINVAL;
220
221 memset ((void *) packet, 0, sizeof (DOOF_BLK));
222
223 /* Fill out packet fields */
224
225 packet->addr = address;
226 packet->len = length;
227
228 len = sizeof (DOOF_BLK);
229
230
231 res =
232 doof_txrx (f, dest_mac, (unsigned char *) packet, DOOF_CMD_READ_BLK, 0,
233 len, buf);
234 free ((void *) packet);
235
236 /* Check if we received expected length */
237 if (res != length)
238 {
239 printf ("read_blk: Incorrect byte-count received (%d / %d)\n", res,
240 length);
241 return -DOOF_RESP_BADSIZE;
242 }
243
244 /* Copy the contents of the payload into the dest. buffer */
245 memcpy ((void *) recv_buf, (void *) buf + 14 + DOOF_PL_OFF, length);
246
247 return res;
248 }
249