|  | @@ -3,6 +3,7 @@
 | 
	
		
			
				|  |  |  #include "spiflash.h"
 | 
	
		
			
				|  |  |  #include "esp.h"
 | 
	
		
			
				|  |  |  #include "matchver.h"
 | 
	
		
			
				|  |  | +#include "boardinfo_fpga.h"
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  #if 1
 | 
	
		
			
				|  |  |  # include "console.h"
 | 
	
	
		
			
				|  | @@ -30,6 +31,7 @@ struct spz_stream {
 | 
	
		
			
				|  |  |  	};
 | 
	
		
			
				|  |  |      };
 | 
	
		
			
				|  |  |      struct fw_header header;	    /* Header of currently processed chunk */
 | 
	
		
			
				|  |  | +    struct fw_header vmatch;	    /* Matched firmware version string */
 | 
	
		
			
				|  |  |      int err;			    /* Error code to return */
 | 
	
		
			
				|  |  |      bool eoi;			    /* Reached end of input */
 | 
	
		
			
				|  |  |      bool cleanup;		    /* Call inflateEnd() */
 | 
	
	
		
			
				|  | @@ -451,7 +453,7 @@ static int spiflash_flash_chunk(spz_stream *spz)
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	    spiflash_check_block(spz, addr, &erase_mask, prog_mask);
 | 
	
		
			
				|  |  |  	    if (erase_mask) {
 | 
	
		
			
				|  |  | -		spz->err = SPIFLASH_ERR_ERASE_FAILED;
 | 
	
		
			
				|  |  | +		spz->err = FWUPDATE_ERR_ERASE_FAILED;
 | 
	
		
			
				|  |  |  		MSG("%04x left, ", erase_mask);
 | 
	
		
			
				|  |  |  		goto err;
 | 
	
		
			
				|  |  |  	    }
 | 
	
	
		
			
				|  | @@ -491,7 +493,7 @@ static int spiflash_flash_chunk(spz_stream *spz)
 | 
	
		
			
				|  |  |  	    if (memcmp(spz->dbuf + page_offs, spz->vbuf + page_offs,
 | 
	
		
			
				|  |  |  		       SPIFLASH_PAGE_SIZE)) {
 | 
	
		
			
				|  |  |  		MSG("verify ");
 | 
	
		
			
				|  |  | -		spz->err = SPIFLASH_ERR_PROGRAM_FAILED;
 | 
	
		
			
				|  |  | +		spz->err = FWUPDATE_ERR_PROGRAM_FAILED;
 | 
	
		
			
				|  |  |  		goto err;
 | 
	
		
			
				|  |  |  	    }
 | 
	
		
			
				|  |  |  	    MSG("ok\n");
 | 
	
	
		
			
				|  | @@ -600,23 +602,89 @@ static int esp_ota_chunk(spz_stream *spz)
 | 
	
		
			
				|  |  |      return spz->err;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -/* Process a data chunk; return a nonzero value if done */
 | 
	
		
			
				|  |  | -static int spiflash_process_chunk(spz_stream *spz)
 | 
	
		
			
				|  |  | +/* Get a piece of the chunk header */
 | 
	
		
			
				|  |  | +static int fwupdate_get_header_data(spz_stream *spz, void *buf, int len)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  |      int rv;
 | 
	
		
			
				|  |  | -    char *str;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    rv = spiflash_read_data(spz, &spz->header, sizeof spz->header);
 | 
	
		
			
				|  |  | +    rv = spiflash_read_data(spz, buf, len);
 | 
	
		
			
				|  |  |      if (spz->err)
 | 
	
		
			
				|  |  |  	return spz->err;
 | 
	
		
			
				|  |  |      else if (!rv)
 | 
	
		
			
				|  |  |  	return Z_STREAM_END;
 | 
	
		
			
				|  |  | -    else if (rv != sizeof spz->header)
 | 
	
		
			
				|  |  | +    else if (rv != len)
 | 
	
		
			
				|  |  |  	return spz->err = Z_STREAM_ERROR;
 | 
	
		
			
				|  |  | +    else
 | 
	
		
			
				|  |  | +	return Z_OK;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    if (spz->header.magic != FW_MAGIC) {
 | 
	
		
			
				|  |  | -	MSG("update: bad chunk header magic 0x%08x\n", spz->header.magic);
 | 
	
		
			
				|  |  | -	return spz->err = Z_DATA_ERROR;
 | 
	
		
			
				|  |  | +/* Get and validate a chunk header */
 | 
	
		
			
				|  |  | +static int fwupdate_get_header(spz_stream *spz)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +    struct fw_header * const hdr = &spz->header;
 | 
	
		
			
				|  |  | +    uint8_t *hptr = (uint8_t *)hdr;
 | 
	
		
			
				|  |  | +    int rv;
 | 
	
		
			
				|  |  | +    unsigned int hlen;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    memset(hdr, 0, sizeof *hdr);
 | 
	
		
			
				|  |  | +    hdr->vmax = -1;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    rv = fwupdate_get_header_data(spz, hptr, FW_HDR_LEN_V1);
 | 
	
		
			
				|  |  | +    if (rv)
 | 
	
		
			
				|  |  | +	return rv;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    switch (hdr->magic) {
 | 
	
		
			
				|  |  | +    case FW_MAGIC_V1:
 | 
	
		
			
				|  |  | +	hlen = FW_HDR_LEN_V1;
 | 
	
		
			
				|  |  | +	break;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    case FW_MAGIC_V2:
 | 
	
		
			
				|  |  | +	hlen = FW_HDR_LEN_V2;
 | 
	
		
			
				|  |  | +	break;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    default:
 | 
	
		
			
				|  |  | +	MSG("update: bad chunk header magic 0x%08x\n", hdr->magic);
 | 
	
		
			
				|  |  | +	hlen = 0;
 | 
	
		
			
				|  |  | +	rv = Z_DATA_ERROR;
 | 
	
		
			
				|  |  | +	break;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    if (hlen > FW_HDR_LEN_V1) {
 | 
	
		
			
				|  |  | +	rv = fwupdate_get_header_data(spz, hptr + FW_HDR_LEN_V1,
 | 
	
		
			
				|  |  | +				      hlen - FW_HDR_LEN_V1);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	if (rv == Z_STREAM_END)	/* Only valid for the first chunk */
 | 
	
		
			
				|  |  | +	    rv = Z_STREAM_ERROR;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    return spz->err = rv;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +/* Process a data chunk; return a nonzero value if done */
 | 
	
		
			
				|  |  | +static int spiflash_process_chunk(spz_stream *spz)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +    int rv;
 | 
	
		
			
				|  |  | +    char *str;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    rv = fwupdate_get_header(spz);
 | 
	
		
			
				|  |  | +    if (rv)
 | 
	
		
			
				|  |  | +	return rv;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    if (spz->header.type != FDT_NOTE &&
 | 
	
		
			
				|  |  | +	spz->header.type != FDT_TARGET &&
 | 
	
		
			
				|  |  | +	spz->header.type != FDT_END &&
 | 
	
		
			
				|  |  | +	!(spz->header.flags & FDF_PRETARGET)) {
 | 
	
		
			
				|  |  | +	if (!spz->vmatch.magic) {
 | 
	
		
			
				|  |  | +	    /* No matching firmware target support */
 | 
	
		
			
				|  |  | +	    return spz->err = FWUPDATE_ERR_NOT_MINE;
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	if (spz->header.vmin > spz->vmatch.vmax ||
 | 
	
		
			
				|  |  | +	    spz->header.vmax < spz->vmatch.vmin ||
 | 
	
		
			
				|  |  | +	    ((spz->header.vmatch ^ spz->header.vmatch) & spz->header.vmask)) {
 | 
	
		
			
				|  |  | +	    /* Chunk not applicable to this target */
 | 
	
		
			
				|  |  | +	    goto skip;
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      con_printf("update: chunk type %u size %u addr 0x%08x\n",
 | 
	
	
		
			
				|  | @@ -630,14 +698,17 @@ static int spiflash_process_chunk(spz_stream *spz)
 | 
	
		
			
				|  |  |  	    goto skip;
 | 
	
		
			
				|  |  |  	return spiflash_flash_chunk(spz);
 | 
	
		
			
				|  |  |      case FDT_TARGET:
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +	bool match;
 | 
	
		
			
				|  |  |  	str = spiflash_read_chunk_str(spz);
 | 
	
		
			
				|  |  | -	/* XXX: replace with proper matching algorithm */
 | 
	
		
			
				|  |  | -	if (!str || !match_version(spz->flash->target, str)) {
 | 
	
		
			
				|  |  | -	    MSG("update: this firmware file targets \"%s\", need \"%s\"\n",
 | 
	
		
			
				|  |  | -		str, spz->flash->target);
 | 
	
		
			
				|  |  | -	    return spz->err = Z_DATA_ERROR;
 | 
	
		
			
				|  |  | -	}
 | 
	
		
			
				|  |  | -	break;
 | 
	
		
			
				|  |  | +	match = match_version(board_info.version_str, str);
 | 
	
		
			
				|  |  | +	if (match || spz->header.magic == FW_MAGIC_V1)
 | 
	
		
			
				|  |  | +	    spz->vmatch = spz->header;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	MSG("update: firmware file supports: %s%s\n",
 | 
	
		
			
				|  |  | +	    str, match ? " (match)" : "");
 | 
	
		
			
				|  |  | +	return Z_OK;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |      case FDT_NOTE:
 | 
	
		
			
				|  |  |  	str = spiflash_read_chunk_str(spz);
 | 
	
		
			
				|  |  |  	MSG("update: %s\n", str);
 |