mirror of
https://github.com/openshwprojects/OpenBK7231T_App.git
synced 2026-03-13 10:48:34 +01:00
OTA for W800 + "Simple OTA" w/o httpd (#1471)
* OTA for W800 Removed unnecessary (and wasting resources) fetching of "index?status=1" on pages not using "state" div Added simple "internal OTA" (just POST-ing a file) Basic tests done - try avoiding other TCP connections to save memory Somtimes there are memory related messages in log like "Thread create HTTP Client - errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY". OTA working in most cases, somtimes device crashes during update. Device will immediatly reboot after OTA completion, even printfs after writing last bytes was not visible in console. * Add some more warnings Make file selector accepting images on extension for platform For Beken: Check magic "RBL" and future Platform name in header * Changed way to verify firmware files: must match OBK file structure for the platform As suggested by @NonPIayerCharacter added "NO_PLATFORM_OTA" in obk_config.h For platforms w/o OTA the page will be only showing a hint. * Fix page for non OTA devices * streamlined tests moved platform dependent #define for OTA extension to obk_config.h * Optimized JS code Only show hint for ".rbl" file on Beken platforms Added a #define OBK_OTA_NAME_EXTENSION, actually only for LN882H (here UART and OTA file are identicaly except an "_OTA" in the file name). Otherwise the UART file would also match the template (this file would not be flashed because of additional checks, but if we can prevent this ...)
This commit is contained in:
@@ -3011,11 +3011,30 @@ int http_fn_ota_exec(http_request_t* request) {
|
||||
int http_fn_ota(http_request_t* request) {
|
||||
http_setup(request, httpMimeTypeHTML);
|
||||
http_html_start(request, "OTA system");
|
||||
poststr(request, "<p>For a more user-friendly experience, it is recommended to use the OTA option in the Web Application, where you can easily drag and drop files without needing to set up a server. On Beken platforms, the .rbl file is used for OTA updates. In the OTA section below, paste the link to the .rbl file (an HTTP server is required).</p>");
|
||||
add_label_text_field(request, "URL for new bin file", "host", "", "<form action=\"/ota_exec\">");
|
||||
#ifndef OBK_OTA_EXTENSION
|
||||
poststr(request, "<h3>Sorry, OTA update not implemented for " DEVICENAME_PREFIX_FULL " </h3>");
|
||||
#else
|
||||
poststr(request, "<p>It's recommended to use the OTA option in the Web Application, where you can easily drag and drop files.<br><br>If you have an HTTP server providing the OTA file, you may enter the URL below. "
|
||||
#if PLATFORM_BEKEN
|
||||
" On Beken platforms, the .rbl file is used for OTA updates."
|
||||
#endif
|
||||
"</p>");
|
||||
add_label_text_field(request, "URL for ota firmware file", "host", "", "<form action=\"/ota_exec\">");
|
||||
poststr(request, "<br>\
|
||||
<input type=\"submit\" value=\"Submit\" onclick=\"return confirm('Are you sure?')\">\
|
||||
</form>");
|
||||
|
||||
const char htmlOTA[] = "<script>var o=document.getElementById('otafile'),d=document.querySelector('dialog'),h=document.getElementById('hint'),D='OTA started! Please wait ',R=/" DEVICENAME_PREFIX_FULL "_.*"
|
||||
#ifdef OBK_OTA_NAME_EXTENSION
|
||||
OBK_OTA_NAME_EXTENSION
|
||||
#endif
|
||||
OBK_OTA_EXTENSION "/,SR=R.source,mr=(e)=>e.name.match(R);doota=()=>{f=o.files[0];if(f&&(f)){d.showModal();var t=30;setTimeout(()=>{d.close(),location.href='/'},1e3*t),setInterval(()=>d.innerHTML=D+t--+' secs',1e3),fetch('/api/ota',{method:'POST',body:f}).then((e)=>{e.ok&&fetch('/index?restart=1')})}else alert(f?'filename invalid':'no file selected')};d.innerHTML=D,o.addEventListener('change',((e)=>{const t=e.target.files[0];if(!t)return;h.innerHTML=mr(t)?'':'Selected file does <b>not</b> match reqired format '+SR+'!'}))</script>";
|
||||
|
||||
poststr(request, "<br><br><br>Expert feature: Upload firmware OTA file.<br>If unsure, please use Web App!<br><span id='hint' style='color: yellow;'></span><br><br>");
|
||||
poststr(request, "<input id='otafile' type='file' accept='" OBK_OTA_EXTENSION "'>");
|
||||
poststr(request, "<input type='button' class='bred' onclick='doota();' value='START OTA - No file check - will reboot after OTA'><dialog></dialog>");
|
||||
poststr(request, htmlOTA);
|
||||
#endif
|
||||
poststr(request, htmlFooterReturnToCfgOrMainPage);
|
||||
http_html_end(request);
|
||||
poststr(request, NULL);
|
||||
|
||||
@@ -46,6 +46,9 @@ uint32_t flash_read(uint32_t flash, uint32_t addr, void* buf, uint32_t size);
|
||||
|
||||
#elif PLATFORM_W800
|
||||
|
||||
#include "wm_socket_fwup.h"
|
||||
#include "wm_fwup.h"
|
||||
|
||||
#elif PLATFORM_LN882H
|
||||
|
||||
#elif PLATFORM_ESPIDF
|
||||
@@ -242,6 +245,8 @@ static int http_rest_post(http_request_t* request) {
|
||||
return http_rest_post_flash(request, START_ADR_OF_BK_PARTITION_OTA, LFS_BLOCKS_END);
|
||||
#elif PLATFORM_W600
|
||||
return http_rest_post_flash(request, -1, -1);
|
||||
#elif PLATFORM_W800
|
||||
return http_rest_post_flash(request, -1, -1);
|
||||
#elif PLATFORM_BL602
|
||||
return http_rest_post_flash(request, -1, -1);
|
||||
#elif PLATFORM_LN882H
|
||||
@@ -1421,7 +1426,7 @@ static int ota_verify_download(void)
|
||||
static int http_rest_post_flash(http_request_t* request, int startaddr, int maxaddr)
|
||||
{
|
||||
|
||||
#if PLATFORM_XR809 || PLATFORM_W800 || PLATFORM_TR6260
|
||||
#if PLATFORM_XR809 || PLATFORM_TR6260
|
||||
return 0; //Operation not supported yet
|
||||
#endif
|
||||
|
||||
@@ -1557,6 +1562,138 @@ static int http_rest_post_flash(http_request_t* request, int startaddr, int maxa
|
||||
}
|
||||
|
||||
|
||||
#elif PLATFORM_W800
|
||||
int nRetCode = 0;
|
||||
char error_message[256];
|
||||
|
||||
if(writelen < 0)
|
||||
{
|
||||
ADDLOG_DEBUG(LOG_FEATURE_OTA, "ABORTED: %d bytes to write", writelen);
|
||||
return http_rest_error(request, -20, "writelen < 0");
|
||||
}
|
||||
|
||||
struct pbuf* p;
|
||||
|
||||
//The code below is based on W600 code and adopted to the differences in sdk\OpenW800\src\app\ota\wm_http_fwup.c
|
||||
// fiexd crashing caused by not checking "writelen" before doing memcpy
|
||||
// e.g. if more than 2 packets arrived before next loop, writelen could be > 2048 !!
|
||||
#define FWUP_MSG_SIZE 3
|
||||
#define MAX_BUFF_SIZE 2048
|
||||
char* Buffer = (char*)os_malloc(MAX_BUFF_SIZE + FWUP_MSG_SIZE);
|
||||
|
||||
if(request->contentLength >= 0)
|
||||
{
|
||||
towrite = request->contentLength;
|
||||
}
|
||||
|
||||
int recvLen = 0;
|
||||
int totalLen = 0;
|
||||
uint8_t counter = 0;
|
||||
printf("\ntowrite %d writelen=%d\n", towrite, writelen);
|
||||
|
||||
do
|
||||
{
|
||||
while(writelen > 0)
|
||||
{
|
||||
int actwrite = writelen < MAX_BUFF_SIZE ? writelen : MAX_BUFF_SIZE; // mustn't write more than Buffers size! Will crash else!
|
||||
//bk_printf("Copying %d from writebuf to Buffer (writelen=%d) towrite=%d -- free_heap:%d\n", actwrite, writelen, towrite, xPortGetFreeHeapSize());
|
||||
memset(Buffer, 0, MAX_BUFF_SIZE + FWUP_MSG_SIZE);
|
||||
memcpy(Buffer + FWUP_MSG_SIZE, writebuf, actwrite);
|
||||
if(recvLen == 0)
|
||||
{
|
||||
IMAGE_HEADER_PARAM_ST *booter = (IMAGE_HEADER_PARAM_ST*)(Buffer + FWUP_MSG_SIZE);
|
||||
bk_printf("magic_no=%u, img_type=%u, zip_type=%u, signature=%u\n",
|
||||
booter->magic_no, booter->img_attr.b.img_type, booter->img_attr.b.zip_type, booter->img_attr.b.signature);
|
||||
|
||||
if(TRUE == tls_fwup_img_header_check(booter))
|
||||
{
|
||||
totalLen = booter->img_len + sizeof(IMAGE_HEADER_PARAM_ST);
|
||||
if (booter->img_attr.b.signature)
|
||||
{
|
||||
totalLen += 128;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(error_message, "Image header check failed");
|
||||
nRetCode = -19;
|
||||
break;
|
||||
}
|
||||
|
||||
nRetCode = socket_fwup_accept(0, ERR_OK);
|
||||
if(nRetCode != ERR_OK)
|
||||
{
|
||||
sprintf(error_message, "Firmware update startup failed");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
p = pbuf_alloc(PBUF_TRANSPORT, actwrite + FWUP_MSG_SIZE, PBUF_REF);
|
||||
if(!p)
|
||||
{
|
||||
sprintf(error_message, "Unable to allocate memory for buffer");
|
||||
nRetCode = -18;
|
||||
break;
|
||||
}
|
||||
|
||||
if(recvLen == 0)
|
||||
{
|
||||
*Buffer = SOCKET_FWUP_START;
|
||||
}
|
||||
else if(recvLen == (totalLen - actwrite))
|
||||
{
|
||||
*Buffer = SOCKET_FWUP_END;
|
||||
}
|
||||
else
|
||||
{
|
||||
*Buffer = SOCKET_FWUP_DATA;
|
||||
}
|
||||
|
||||
*(Buffer + 1) = (actwrite >> 8) & 0xFF;
|
||||
*(Buffer + 2) = actwrite & 0xFF;
|
||||
p->payload = Buffer;
|
||||
p->len = p->tot_len = actwrite + FWUP_MSG_SIZE;
|
||||
|
||||
nRetCode = socket_fwup_recv(0, p, ERR_OK);
|
||||
if(nRetCode != ERR_OK)
|
||||
{
|
||||
sprintf(error_message, "Firmware data processing failed");
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
recvLen += actwrite;
|
||||
}
|
||||
|
||||
towrite -= actwrite;
|
||||
writelen -= actwrite; // calculate, how much is left to write
|
||||
writebuf += actwrite; // in case, we only wrote part of buffer, advance in buffer
|
||||
}
|
||||
|
||||
if(towrite > 0)
|
||||
{
|
||||
writebuf = request->received;
|
||||
writelen = recv(request->fd, writebuf, request->receivedLenmax, 0);
|
||||
if(writelen < 0)
|
||||
{
|
||||
sprintf(error_message, "recv returned %d - end of data - remaining %d", writelen, towrite);
|
||||
nRetCode = -17;
|
||||
}
|
||||
}
|
||||
if (counter++ % 5 == 0) bk_printf("Downloaded %d / %d\n", recvLen, totalLen);
|
||||
rtos_delay_milliseconds(10); // give some time for flashing - will else increase used memory fast
|
||||
} while((nRetCode == 0) && (towrite > 0) && (writelen >= 0));
|
||||
bk_printf("Download completed (%d / %d)\n", recvLen, totalLen);
|
||||
tls_mem_free(Buffer);
|
||||
|
||||
if(nRetCode != 0)
|
||||
{
|
||||
ADDLOG_ERROR(LOG_FEATURE_OTA, error_message);
|
||||
socket_fwup_err(0, nRetCode);
|
||||
return http_rest_error(request, nRetCode, error_message);
|
||||
}
|
||||
|
||||
|
||||
#elif PLATFORM_BL602
|
||||
int sockfd, i;
|
||||
int ret;
|
||||
|
||||
Reference in New Issue
Block a user