* Send an image to the EC in burst-sized chunks. */
| 240 | * Send an image to the EC in burst-sized chunks. |
| 241 | */ |
| 242 | static vb2_error_t ec_flash_write(void *image, uint32_t region_offset, |
| 243 | int image_size) |
| 244 | { |
| 245 | struct ec_response_get_protocol_info resp_proto; |
| 246 | struct ec_response_flash_info resp_flash; |
| 247 | ssize_t pdata_max_size; |
| 248 | ssize_t burst; |
| 249 | uint8_t *file_buf; |
| 250 | struct ec_params_flash_write *params; |
| 251 | uint32_t end, off; |
| 252 | |
| 253 | /* |
| 254 | * Get EC's protocol information, so that we can figure out how much |
| 255 | * data can be sent in one message. |
| 256 | */ |
| 257 | if (google_chromeec_get_protocol_info(&resp_proto)) { |
| 258 | printk(BIOS_ERR, "Failed to get EC protocol information; " |
| 259 | "skipping flash write\n"); |
| 260 | return VB2_ERROR_UNKNOWN; |
| 261 | } |
| 262 | |
| 263 | /* |
| 264 | * Determine burst size. This must be a multiple of the write block |
| 265 | * size, and must also fit into the host parameter buffer. |
| 266 | */ |
| 267 | if (google_chromeec_flash_info(&resp_flash)) { |
| 268 | printk(BIOS_ERR, "Failed to get EC flash information; " |
| 269 | "skipping flash write\n"); |
| 270 | return VB2_ERROR_UNKNOWN; |
| 271 | } |
| 272 | |
| 273 | /* Limit the potential buffer stack allocation to 1K */ |
| 274 | pdata_max_size = MIN(1024, resp_proto.max_request_packet_size - |
| 275 | sizeof(struct ec_host_request)); |
| 276 | |
| 277 | /* Round burst to a multiple of the flash write block size */ |
| 278 | burst = pdata_max_size - sizeof(*params); |
| 279 | burst = (burst / resp_flash.write_block_size) * |
| 280 | resp_flash.write_block_size; |
| 281 | |
| 282 | /* Buffer too small */ |
| 283 | if (burst <= 0) { |
| 284 | printk(BIOS_ERR, "Flash write buffer too small! skipping " |
| 285 | "flash write\n"); |
| 286 | return VB2_ERROR_UNKNOWN; |
| 287 | } |
| 288 | |
| 289 | /* Allocate buffer on the stack */ |
| 290 | params = alloca(burst + sizeof(*params)); |
| 291 | |
| 292 | /* Fill up the buffer */ |
| 293 | end = region_offset + image_size; |
| 294 | file_buf = image; |
| 295 | for (off = region_offset; off < end; off += burst) { |
| 296 | uint32_t todo = MIN(end - off, burst); |
| 297 | uint32_t xfer_size = todo + sizeof(*params); |
| 298 | |
| 299 | params->offset = off; |
no test coverage detected