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