intermediate: handle flusing of s3 images in webinstaller

This commit is contained in:
andreas 2023-09-09 13:01:00 +02:00
parent e8c6a72a43
commit 4fcf6b753f
2 changed files with 37 additions and 15 deletions

View File

@ -4,7 +4,6 @@ import { addEl, getParam, setValue, setVisible } from "./helper.js";
import * as zip from "https://cdn.jsdelivr.net/npm/@zip.js/zip.js@2.7.29/+esm"; import * as zip from "https://cdn.jsdelivr.net/npm/@zip.js/zip.js@2.7.29/+esm";
(function(){ (function(){
const FULL_START=4096;
const UPDATE_START=65536; const UPDATE_START=65536;
//taken from index.js //taken from index.js
@ -13,6 +12,7 @@ import * as zip from "https://cdn.jsdelivr.net/npm/@zip.js/zip.js@2.7.29/+esm";
const NAMEOFFSET = 48; const NAMEOFFSET = 48;
const CHIPOFFSET=NAMEOFFSET+64; const CHIPOFFSET=NAMEOFFSET+64;
const MINSIZE = HDROFFSET + CHIPOFFSET + 32; const MINSIZE = HDROFFSET + CHIPOFFSET + 32;
const CHIPIDOFFSET=12; //2 bytes chip id here
const imageMagic=0xe9; //at byte 0 const imageMagic=0xe9; //at byte 0
const imageCheckBytes = { const imageCheckBytes = {
288: 0x32, //app header magic 288: 0x32, //app header magic
@ -20,6 +20,14 @@ import * as zip from "https://cdn.jsdelivr.net/npm/@zip.js/zip.js@2.7.29/+esm";
290: 0xcd, 290: 0xcd,
291: 0xab 291: 0xab
}; };
/**
* map of our known chip ids to flash starts for full images
* 9 - esp32s3 - starts at 0
*/
const FLASHSTART={
0:0x1000,
9:0
};
const decodeFromBuffer=(buffer, start, length)=>{ const decodeFromBuffer=(buffer, start, length)=>{
while (length > 0 && buffer.charCodeAt(start + length - 1) == 0) { while (length > 0 && buffer.charCodeAt(start + length - 1) == 0) {
length--; length--;
@ -27,13 +35,25 @@ import * as zip from "https://cdn.jsdelivr.net/npm/@zip.js/zip.js@2.7.29/+esm";
if (length <= 0) return ""; if (length <= 0) return "";
return buffer.substr(start,length); return buffer.substr(start,length);
} }
const getChipId=(buffer)=>{
if (buffer.length < CHIPIDOFFSET+2) return -1;
return buffer.charCodeAt(CHIPIDOFFSET)+256*buffer.charCodeAt(CHIPIDOFFSET+1);
}
/** /**
* *
* @param {string} content the content to be checked * @param {string} content the content to be checked
*/ */
const checkImage = (content,isFull) => { const checkImage = (content,isFull) => {
let prfx=isFull?"full":"update"; let prfx=isFull?"full":"update";
let startOffset=isFull?(UPDATE_START-FULL_START):0; let startOffset=0;
let flashStart=UPDATE_START;
if (isFull){
let chipId=getChipId(content);
if (chipId < 0) throw new Error(prfx+"image: no valid chip id found");
let flashStart=FLASHSTART[chipId];
if (flashStart === undefined) throw new Error(prfx+"image: unknown chip id "+chipId);
startOffset=UPDATE_START-flashStart;
}
if (content.length < (MINSIZE+startOffset)) { if (content.length < (MINSIZE+startOffset)) {
throw new Error(prfx+"image to small, only " + content.length + " expected " + (MINSIZE+startOffset)); throw new Error(prfx+"image to small, only " + content.length + " expected " + (MINSIZE+startOffset));
} }
@ -53,7 +73,8 @@ import * as zip from "https://cdn.jsdelivr.net/npm/@zip.js/zip.js@2.7.29/+esm";
let rt = { let rt = {
fwtype: fwtype, fwtype: fwtype,
version: version, version: version,
chip:chip chip:chip,
flashStart: flashStart
}; };
return rt; return rt;
} }
@ -260,7 +281,7 @@ import * as zip from "https://cdn.jsdelivr.net/npm/@zip.js/zip.js@2.7.29/+esm";
user, user,
repo, repo,
version, version,
4096, item.basic,
checkChip checkChip
) )
enableConsole(true); enableConsole(true);
@ -273,7 +294,7 @@ import * as zip from "https://cdn.jsdelivr.net/npm/@zip.js/zip.js@2.7.29/+esm";
user, user,
repo, repo,
version, version,
65536, item.update,
checkChip checkChip
) )
enableConsole(true); enableConsole(true);
@ -286,12 +307,14 @@ import * as zip from "https://cdn.jsdelivr.net/npm/@zip.js/zip.js@2.7.29/+esm";
if (!bFrame) return; if (!bFrame) return;
if (fullData === undefined && updateData === undefined) return; if (fullData === undefined && updateData === undefined) return;
let version; let version;
let vinfo;
let uinfo;
if (fullData !== undefined){ if (fullData !== undefined){
let vinfo=checkImage(fullData,true); vinfo=checkImage(fullData,true);
version=vinfo.version; version=vinfo.version;
} }
if (updateData !== undefined){ if (updateData !== undefined){
let uinfo=checkImage(updateData); uinfo=checkImage(updateData);
if (version !== undefined){ if (version !== undefined){
if (uinfo.version != version){ if (uinfo.version != version){
throw new Error("different versions in full("+version+") and update("+uinfo.version+") image"); throw new Error("different versions in full("+version+") and update("+uinfo.version+") image");
@ -316,7 +339,7 @@ import * as zip from "https://cdn.jsdelivr.net/npm/@zip.js/zip.js@2.7.29/+esm";
await espInstaller.runFlash( await espInstaller.runFlash(
true, true,
fullData, fullData,
FULL_START, vinfo.flashStart,
version, version,
checkChip checkChip
) )
@ -330,7 +353,7 @@ import * as zip from "https://cdn.jsdelivr.net/npm/@zip.js/zip.js@2.7.29/+esm";
await espInstaller.runFlash( await espInstaller.runFlash(
false, false,
updateData, updateData,
UPDATE_START, uinfo.flashStart,
version, version,
checkChip checkChip
) )

View File

@ -235,22 +235,21 @@ class ESPInstaller{
* @param {*} user * @param {*} user
* @param {*} repo * @param {*} repo
* @param {*} version * @param {*} version
* @param {*} address * @param {*} assetName
* @param {*} checkChip will be called with the found chip and the data and the isFull flag * @param {*} checkChip will be called with the found chip and the data and the isFull flag
* must return an info with the flashStart being set
* @returns * @returns
*/ */
async installClicked(isFull, user, repo, version, address, assetName) { async installClicked(isFull, user, repo, version, assetName,checkChip) {
try { try {
await this.connect(); await this.connect();
let imageData = await this.getReleaseAsset(user, repo, version, assetName); let imageData = await this.getReleaseAsset(user, repo, version, assetName);
if (!imageData || imageData.length == 0) { if (!imageData || imageData.length == 0) {
throw new Error(`no image data fetched`); throw new Error(`no image data fetched`);
} }
if (checkChip) { let info=await checkChip(this.getChipFamily(),imageData,isFull);
await checkChip(this.getChipFamily(),imageData,isFull);
}
let fileList = [ let fileList = [
{ data: imageData, address: address } { data: imageData, address: info.flashAddress }
]; ];
let txt = isFull ? "baseImage (all data will be erased)" : "update"; let txt = isFull ? "baseImage (all data will be erased)" : "update";
if (!confirm(`ready to install ${version}\n${txt}`)) { if (!confirm(`ready to install ${version}\n${txt}`)) {