uboot-2025: add glinet failsafe webui

This commit is contained in:
hanwckf
2025-08-21 12:48:34 +08:00
parent 0f5d75e752
commit f58deb97cb
18 changed files with 910 additions and 252 deletions

View File

@@ -11,12 +11,26 @@
#include <errno.h>
#include <linux/string.h>
#include <asm/global_data.h>
#include <failsafe/fw_type.h>
#ifdef CONFIG_CMD_GL_BTN
#include <glbtn.h>
#endif
#include "upgrade_helper.h"
#include "colored_print.h"
DECLARE_GLOBAL_DATA_PTR;
#define UPGRADE_PART "fw"
const char *fw_to_part_name(failsafe_fw_t fw)
{
switch (fw)
{
case FW_TYPE_GPT: return "gpt";
case FW_TYPE_BL2: return "bl2";
case FW_TYPE_FIP: return "fip";
case FW_TYPE_FW: return "fw";
default: return "err";
}
}
static const struct data_part_entry *find_part(const struct data_part_entry *parts,
u32 num_parts, const char *abbr)
@@ -42,7 +56,7 @@ void *httpd_get_upload_buffer_ptr(size_t size)
return (void *)gd->ram_base + 0x4000000;
}
int failsafe_validate_image(const void *data, size_t size)
int failsafe_validate_image(const void *data, size_t size, failsafe_fw_t fw)
{
const struct data_part_entry *upgrade_parts, *dpe;
u32 num_parts;
@@ -54,7 +68,7 @@ int failsafe_validate_image(const void *data, size_t size)
return -ENOSYS;
}
dpe = find_part(upgrade_parts, num_parts, UPGRADE_PART);
dpe = find_part(upgrade_parts, num_parts, fw_to_part_name(fw));
if (!dpe)
return -ENODEV;
@@ -64,7 +78,7 @@ int failsafe_validate_image(const void *data, size_t size)
return 0;
}
int failsafe_write_image(const void *data, size_t size)
int failsafe_write_image(const void *data, size_t size, failsafe_fw_t fw)
{
const struct data_part_entry *upgrade_parts, *dpe;
u32 num_parts;
@@ -77,10 +91,14 @@ int failsafe_write_image(const void *data, size_t size)
return -ENOSYS;
}
dpe = find_part(upgrade_parts, num_parts, UPGRADE_PART);
dpe = find_part(upgrade_parts, num_parts, fw_to_part_name(fw));
if (!dpe)
return -ENODEV;
#ifdef CONFIG_CMD_GL_BTN
led_control("led", "system_led", "off");
led_control("ledblink", "blink_led", "100");
#endif
printf("\n");
cprintln(PROMPT, "*** Upgrading %s ***", dpe->name);
cprintln(PROMPT, "*** Data: %zd (0x%zx) bytes at 0x%08lx ***",
@@ -88,6 +106,10 @@ int failsafe_write_image(const void *data, size_t size)
printf("\n");
ret = dpe->write(dpe->priv, dpe, data, size);
#ifdef CONFIG_CMD_GL_BTN
led_control("ledblink", "blink_led", "0");
led_control("led", "system_led", "on");
#endif
if (ret)
return ret;

View File

@@ -9,25 +9,39 @@
#include <command.h>
#include <errno.h>
#include <env.h>
#include <malloc.h>
#include <net.h>
#include <net/mtk_tcp.h>
#include <net/mtk_httpd.h>
#include <u-boot/md5.h>
#include <linux/stringify.h>
#include <dm/ofnode.h>
#include <vsprintf.h>
#include <version_string.h>
#include <failsafe/fw_type.h>
#include "../board/mediatek/common/boot_helper.h"
#include "fs.h"
static u32 upload_data_id;
static const void *upload_data;
static size_t upload_size;
static int upgrade_success;
static failsafe_fw_t fw_type;
int __weak failsafe_validate_image(const void *data, size_t size)
#ifdef CONFIG_MEDIATEK_MULTI_MTD_LAYOUT
static const char *mtd_layout_label;
const char *get_mtd_layout_label(void);
#define MTD_LAYOUTS_MAXLEN 128
#endif
int __weak failsafe_validate_image(const void *data, size_t size, failsafe_fw_t fw)
{
return 0;
}
int __weak failsafe_write_image(const void *data, size_t size)
int __weak failsafe_write_image(const void *data, size_t size, failsafe_fw_t fw)
{
return -ENOSYS;
}
@@ -58,6 +72,23 @@ static int output_plain_file(struct httpd_response *response,
return ret;
}
static void version_handler(enum httpd_uri_handler_status status,
struct httpd_request *request,
struct httpd_response *response)
{
if (status != HTTP_CB_NEW)
return;
response->status = HTTP_RESP_STD;
response->data = version_string;
response->size = strlen(response->data);
response->info.code = 200;
response->info.connection_close = 1;
response->info.content_type = "text/plain";
}
static void index_handler(enum httpd_uri_handler_status status,
struct httpd_request *request,
struct httpd_response *response)
@@ -66,109 +97,107 @@ static void index_handler(enum httpd_uri_handler_status status,
output_plain_file(response, "index.html");
}
struct upload_status {
bool free_response_data;
};
static void upload_handler(enum httpd_uri_handler_status status,
struct httpd_request *request,
struct httpd_response *response)
{
char *buff, *md5_ptr, *size_ptr, size_str[16];
static char md5_str[33] = "";
static char resp[128];
struct httpd_form_value *fw;
struct upload_status *us;
#ifdef CONFIG_MEDIATEK_MULTI_MTD_LAYOUT
struct httpd_form_value *mtd = NULL;
#endif
u8 md5_sum[16];
int i;
static char hexchars[] = "0123456789abcdef";
if (status == HTTP_CB_NEW) {
us = calloc(1, sizeof(*us));
if (!us) {
response->info.code = 500;
return;
}
response->session_data = us;
fw = httpd_request_find_value(request, "firmware");
if (!fw) {
response->info.code = 302;
response->info.connection_close = 1;
response->info.location = "/";
return;
}
if (failsafe_validate_image(fw->data, fw->size)) {
if (output_plain_file(response, "validate_fail.html"))
response->info.code = 500;
return;
}
if (output_plain_file(response, "upload.html")) {
response->info.code = 500;
return;
}
buff = malloc(response->size + 1);
if (buff) {
memcpy(buff, response->data, response->size);
buff[response->size] = 0;
md5_ptr = strstr(buff, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");
size_ptr = strstr(buff, "YYYYYYYYYY");
if (md5_ptr) {
md5_wd((u8 *)fw->data, fw->size, md5_sum, MD5_DEF_CHUNK_SZ);
for (i = 0; i < 16; i++) {
u8 hex;
hex = (md5_sum[i] >> 4) & 0xf;
md5_ptr[i * 2] = hexchars[hex];
hex = md5_sum[i] & 0xf;
md5_ptr[i * 2 + 1] = hexchars[hex];
}
}
if (size_ptr) {
u32 n;
n = snprintf(size_str, sizeof(size_str), "%zu",
fw->size);
memset(size_str + n, ' ', sizeof(size_str) - n);
memcpy(size_ptr, size_str, 10);
}
response->data = buff;
us->free_response_data = true;
}
upload_data_id = upload_id;
upload_data = fw->data;
upload_size = fw->size;
if (status != HTTP_CB_NEW)
return;
response->status = HTTP_RESP_STD;
response->info.code = 200;
response->info.connection_close = 1;
response->info.content_type = "text/plain";
#ifdef CONFIG_MTK_BOOTMENU_MMC
fw = httpd_request_find_value(request, "gpt");
if (fw) {
fw_type = FW_TYPE_GPT;
goto done;
}
#endif
fw = httpd_request_find_value(request, "fip");
if (fw) {
fw_type = FW_TYPE_FIP;
if (failsafe_validate_image(fw->data, fw->size, fw_type))
goto fail;
goto done;
}
if (status == HTTP_CB_CLOSED) {
if (response->session_data) {
us = response->session_data;
if (us->free_response_data)
free((void *)response->data);
free(response->session_data);
}
fw = httpd_request_find_value(request, "bl2");
if (fw) {
fw_type = FW_TYPE_BL2;
if (failsafe_validate_image(fw->data, fw->size, fw_type))
goto fail;
goto done;
}
}
static void flashing_handler(enum httpd_uri_handler_status status,
struct httpd_request *request,
struct httpd_response *response)
{
if (status == HTTP_CB_NEW)
output_plain_file(response, "flashing.html");
fw = httpd_request_find_value(request, "firmware");
if (fw) {
fw_type = FW_TYPE_FW;
if (failsafe_validate_image(fw->data, fw->size, fw_type))
goto fail;
#ifdef CONFIG_MEDIATEK_MULTI_MTD_LAYOUT
mtd = httpd_request_find_value(request, "mtd_layout");
#endif
goto done;
}
fw = httpd_request_find_value(request, "initramfs");
if (fw) {
fw_type = FW_TYPE_INITRD;
if (fdt_check_header(fw->data))
goto fail;
goto done;
}
fail:
response->data = "fail";
response->size = strlen(response->data);
return;
done:
upload_data_id = upload_id;
upload_data = fw->data;
upload_size = fw->size;
md5_wd((u8 *)fw->data, fw->size, md5_sum, 0);
for (i = 0; i < 16; i++) {
u8 hex = (md5_sum[i] >> 4) & 0xf;
md5_str[i * 2] = hexchars[hex];
hex = md5_sum[i] & 0xf;
md5_str[i * 2 + 1] = hexchars[hex];
}
#ifdef CONFIG_MEDIATEK_MULTI_MTD_LAYOUT
if (mtd) {
mtd_layout_label = mtd->data;
sprintf(resp, "%ld %s %s", fw->size, md5_str, mtd->data);
} else {
sprintf(resp, "%ld %s", fw->size, md5_str);
}
#else
sprintf(resp, "%ld %s", fw->size, md5_str);
#endif
response->data = resp;
response->size = strlen(response->data);
return;
}
struct flashing_status {
@@ -181,7 +210,6 @@ static void result_handler(enum httpd_uri_handler_status status,
struct httpd_request *request,
struct httpd_response *response)
{
const struct fs_desc *file;
struct flashing_status *st;
u32 size;
@@ -221,29 +249,31 @@ static void result_handler(enum httpd_uri_handler_status status,
return;
}
if (upload_data_id == upload_id)
st->ret = failsafe_write_image(upload_data,
upload_size);
if (upload_data_id == upload_id) {
#ifdef CONFIG_MEDIATEK_MULTI_MTD_LAYOUT
if (mtd_layout_label &&
strcmp(get_mtd_layout_label(), mtd_layout_label) != 0) {
printf("httpd: saving mtd_layout_label: %s\n", mtd_layout_label);
env_set("mtd_layout_label", mtd_layout_label);
env_save();
}
#endif
if (fw_type == FW_TYPE_INITRD)
st->ret = 0;
else
st->ret = failsafe_write_image(upload_data,
upload_size, fw_type);
}
/* invalidate upload identifier */
upload_data_id = rand();
if (!st->ret)
file = fs_find_file("success.html");
response->data = "success";
else
file = fs_find_file("fail.html");
response->data = "failed";
if (!file) {
if (!st->ret)
response->data = "Upgrade completed!";
else
response->data = "Upgrade failed!";
response->size = strlen(response->data);
return;
}
response->data = file->data;
response->size = file->size;
response->size = strlen(response->data);
st->body_sent = 1;
@@ -272,6 +302,16 @@ static void style_handler(enum httpd_uri_handler_status status,
}
}
static void js_handler(enum httpd_uri_handler_status status,
struct httpd_request *request,
struct httpd_response *response)
{
if (status == HTTP_CB_NEW) {
output_plain_file(response, "main.js");
response->info.content_type = "text/javascript";
}
}
static void not_found_handler(enum httpd_uri_handler_status status,
struct httpd_request *request,
struct httpd_response *response)
@@ -282,6 +322,59 @@ static void not_found_handler(enum httpd_uri_handler_status status,
}
}
static void html_handler(enum httpd_uri_handler_status status,
struct httpd_request *request,
struct httpd_response *response)
{
if (status != HTTP_CB_NEW)
return;
if (output_plain_file(response, request->urih->uri + 1))
not_found_handler(status, request, response);
}
#ifdef CONFIG_MEDIATEK_MULTI_MTD_LAYOUT
static const char *get_mtdlayout_str(void)
{
static char mtd_layout_str[MTD_LAYOUTS_MAXLEN];
ofnode node, layout;
sprintf(mtd_layout_str, "%s;", get_mtd_layout_label());
node = ofnode_path("/mtd-layout");
if (ofnode_valid(node) && ofnode_get_child_count(node)) {
ofnode_for_each_subnode(layout, node) {
strcat(mtd_layout_str, ofnode_read_string(layout, "label"));
strcat(mtd_layout_str, ";");
}
}
return mtd_layout_str;
}
#endif
static void mtd_layout_handler(enum httpd_uri_handler_status status,
struct httpd_request *request,
struct httpd_response *response)
{
if (status != HTTP_CB_NEW)
return;
response->status = HTTP_RESP_STD;
#ifdef CONFIG_MEDIATEK_MULTI_MTD_LAYOUT
response->data = get_mtdlayout_str();
#else
response->data = "error";
#endif
response->size = strlen(response->data);
response->info.code = 200;
response->info.connection_close = 1;
response->info.content_type = "text/plain";
}
int start_web_failsafe(void)
{
struct httpd_instance *inst;
@@ -297,11 +390,23 @@ int start_web_failsafe(void)
}
httpd_register_uri_handler(inst, "/", &index_handler, NULL);
httpd_register_uri_handler(inst, "/bl2.html", &html_handler, NULL);
httpd_register_uri_handler(inst, "/booting.html", &html_handler, NULL);
httpd_register_uri_handler(inst, "/cgi-bin/luci", &index_handler, NULL);
httpd_register_uri_handler(inst, "/upload", &upload_handler, NULL);
httpd_register_uri_handler(inst, "/flashing", &flashing_handler, NULL);
httpd_register_uri_handler(inst, "/cgi-bin/luci/", &index_handler, NULL);
httpd_register_uri_handler(inst, "/fail.html", &html_handler, NULL);
httpd_register_uri_handler(inst, "/flashing.html", &html_handler, NULL);
httpd_register_uri_handler(inst, "/getmtdlayout", &mtd_layout_handler, NULL);
#ifdef CONFIG_MTK_BOOTMENU_MMC
httpd_register_uri_handler(inst, "/gpt.html", &html_handler, NULL);
#endif
httpd_register_uri_handler(inst, "/initramfs.html", &html_handler, NULL);
httpd_register_uri_handler(inst, "/main.js", &js_handler, NULL);
httpd_register_uri_handler(inst, "/result", &result_handler, NULL);
httpd_register_uri_handler(inst, "/style.css", &style_handler, NULL);
httpd_register_uri_handler(inst, "/uboot.html", &html_handler, NULL);
httpd_register_uri_handler(inst, "/upload", &upload_handler, NULL);
httpd_register_uri_handler(inst, "/version", &version_handler, NULL);
httpd_register_uri_handler(inst, "", &not_found_handler, NULL);
net_loop(MTK_TCP);
@@ -312,9 +417,15 @@ int start_web_failsafe(void)
static int do_httpd(struct cmd_tbl *cmdtp, int flag, int argc,
char *const argv[])
{
u32 local_ip = ntohl(net_ip.s_addr);
u32 local_ip;
int ret;
#ifdef CONFIG_NET_FORCE_IPADDR
net_ip = string_to_ip(CONFIG_IPADDR);
net_netmask = string_to_ip(CONFIG_NETMASK);
#endif
local_ip = ntohl(net_ip.s_addr);
printf("\nWeb failsafe UI started\n");
printf("URL: http://%u.%u.%u.%u/\n",
(local_ip >> 24) & 0xff, (local_ip >> 16) & 0xff,
@@ -323,8 +434,12 @@ static int do_httpd(struct cmd_tbl *cmdtp, int flag, int argc,
ret = start_web_failsafe();
if (upgrade_success)
do_reset(NULL, 0, 0, NULL);
if (upgrade_success) {
if (fw_type == FW_TYPE_INITRD)
boot_from_mem((ulong)upload_data);
else
do_reset(NULL, 0, 0, NULL);
}
return ret;
}

View File

@@ -1,15 +1,18 @@
<!DOCTYPE html>
<!DOCTYPE HTML>
<html>
<head>
<title>404 - MediaTek System Recovery Mode</title>
<link rel="stylesheet" type="text/css" href="/style.css">
</head>
<body>
<div id="banner">
MediaTek U-Boot System Recovery Mode
</div>
<div id="main">
<p><strong>Page not found</strong></p>
</div>
</body>
</html>
<head>
<meta charset="utf-8">
<meta http-equiv="Cache-Control" content="no-cache" />
<meta http-equiv="refresh" content="2; URL=/" />
<title>Page not found</title>
<link rel="stylesheet" href="/style.css">
<script src="/main.js"></script>
</head>
<body onload="getversion()">
<div id="m">
<h1 class="red">PAGE NOT FOUND</h1>
<div class="i e">The page you were looking for doesn't exist!</div>
</div>
<div id="version"></div>
</body>
</html>

View File

@@ -5,38 +5,50 @@
# FILE_XXXX.o := YYYY.html <- actual html file to be embedded
# FSPATH_XXXX.o := ZZZ/WWW.EXT <- virtual fs path to be used inside u-boot
obj-y += index.o
FILE_index.o := index.html
FSPATH_index.o := index.html
obj-y += 404.o
FILE_404.o := 404.html
FSPATH_404.o := 404.html
obj-y += upload.o
FILE_upload.o := upload.html
FSPATH_upload.o := upload.html
obj-y += bl2.o
FILE_bl2.o := bl2.html
FSPATH_bl2.o := bl2.html
obj-y += flashing.o
FILE_flashing.o := flashing.html
FSPATH_flashing.o := flashing.html
obj-y += success.o
FILE_success.o := success.html
FSPATH_success.o := success.html
obj-y += booting.o
FILE_booting.o := booting.html
FSPATH_booting.o := booting.html
obj-y += fail.o
FILE_fail.o := fail.html
FSPATH_fail.o := fail.html
obj-y += validate_fail.o
FILE_validate_fail.o := validate_fail.html
FSPATH_validate_fail.o := validate_fail.html
obj-y += flashing.o
FILE_flashing.o := flashing.html
FSPATH_flashing.o := flashing.html
obj-y += 404.o
FILE_404.o := 404.html
FSPATH_404.o := 404.html
obj-y += gpt.o
FILE_gpt.o := gpt.html
FSPATH_gpt.o := gpt.html
obj-y += index.o
FILE_index.o := index.html
FSPATH_index.o := index.html
obj-y += initramfs.o
FILE_initramfs.o := initramfs.html
FSPATH_initramfs.o := initramfs.html
obj-y += main.o
FILE_main.o := main.js
FSPATH_main.o := main.js
obj-y += style.o
FILE_style.o := style.css
FSPATH_style.o := style.css
obj-y += uboot.o
FILE_uboot.o := uboot.html
FSPATH_uboot.o := uboot.html
# customized build rules
strip_path = $(subst /,_,$(subst -,_,$(subst .,_,$(1))))
@@ -60,3 +72,7 @@ $(obj)/%.o: $(src)/%.html FORCE
$(obj)/%.o: $(src)/%.css FORCE
$(call cmd,force_checksrc)
$(call if_changed_dep,as_o_html)
$(obj)/%.o: $(src)/%.js FORCE
$(call cmd,force_checksrc)
$(call if_changed_dep,as_o_html)

View File

@@ -0,0 +1,41 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>BL2 update</title>
<link rel="stylesheet" href="/style.css">
<script src="/main.js"></script>
</head>
<body onload="getversion()">
<div id="m">
<h1>BL2 UPDATE</h1>
<p id="hint">
You are going to update <strong>BL2 (preloader)</strong> on the device.<br>
Please, choose file from your local hard drive and click <strong>Upload</strong> button.
</p>
<form id="form">
<input id="file" type="file" name="bl2">
<input type="button" value="Upload" onclick="upload('bl2')">
</form>
<div>
<div class="bar" id="bar" style="display: none; --percent: 0;"></div>
</div>
<div id="size" style="display: none;">Size: xxxx</div>
<div id="md5" style="display: none;">MD5: xxxx</div>
<div id="upgrade" style="display: none;">
<p>If all information above is correct, click "Update".</p>
<button class="button" onclick="location = '/flashing.html'">Update</button>
</div>
<div class="i w">
<strong>WARNINGS</strong>
<ul>
<li>do not power off the device during update</li>
<li>if everything goes well, the device will restart</li>
<li>you can upload whatever you want, so be sure that you choose proper BL2 image for your device</li>
<li>updating BL2 is a very dangerous operation and may damage your device!</li>
</ul>
</div>
</div>
<div id="version"></div>
</body>
</html>

View File

@@ -0,0 +1,39 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Booting initramfs</title>
<link rel="stylesheet" href="/style.css">
<script src="/main.js"></script>
<script>
function init() {
getversion();
ajax({
url: '/result',
done: function(response) {
if (response == 'failed') {
location = '/fail.html'
return
}
document.getElementById('title').innerHTML = 'BOOT SUCCESS'
document.getElementById('info').innerHTML = 'Your device was successfully booted into initramfs!'
},
timeout: 30000
})
}
</script>
</head>
<body onload="init()">
<div id="m">
<h1 id="title">BOOTING INITRAMFS</h1>
<p id="info">
Your file was successfully uploaded! Booting is in progress, please wait...<br>
This page may be in not responding status for a short time.
</p>
<div id="l"></div>
</div>
<div id="version"></div>
</body>
</html>

View File

@@ -1,2 +1,16 @@
<p><strong>Upgrade failed!</strong></p>
<p><input type="button" value="Return" onclick="location='/'" /></p>
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Update failed</title>
<link rel="stylesheet" href="/style.css">
<script src="/main.js"></script>
</head>
<body onload="getversion()">
<div id="m">
<h1 class="red">UPDATE FAILED</h1>
<div class="i e"><strong>Something went wrong during update</strong>Probably you have chosen wrong file. Please, try again or contact with the author of this modification. You can also get more information during update in U-Boot console.</div>
</div>
<div id="version"></div>
</body>
</html>

View File

@@ -1,32 +1,39 @@
<!DOCTYPE html>
<!DOCTYPE HTML>
<html>
<head>
<title>Flashing - MediaTek System Recovery Mode</title>
<link rel="stylesheet" type="text/css" href="/style.css">
</head>
<body>
<div id="banner">
MediaTek U-Boot System Recovery Mode
</div>
<div id="main">
<p>Upgrading is in progressing, please wait ...</p>
<p>This page may be in not responding status for a short time.</p>
</div>
<script type="text/javascript">
var interval = window.setInterval(function () {
var xmlhttp = new XMLHttpRequest();
<head>
<meta charset="utf-8">
<title>Update in progress</title>
<link rel="stylesheet" href="/style.css">
<script src="/main.js"></script>
<script>
function init() {
getversion();
window.clearInterval(interval);
ajax({
url: '/result',
done: function(response) {
if (response == 'failed') {
location = '/fail.html'
return
}
xmlhttp.timeout = 300000;
xmlhttp.open("GET", "/result", true);
xmlhttp.send();
xmlhttp.onreadystatechange = function () {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
document.getElementById("main").innerHTML = xmlhttp.responseText;
}
document.getElementById('title').innerHTML = 'UPDATE COMPLETED'
document.getElementById('info').innerHTML = 'Your device was successfully updated! Now rebooting...'
},
timeout: 1800000
})
}
}, 1000);
</script>
</body>
</html>
</script>
</head>
<body onload="init()">
<div id="m">
<h1 id="title">UPDATE IN PROGRESS</h1>
<p id="info">
Your file was successfully uploaded! Update is in progress and you should wait for automatic reset of the device.<br>
Update time depends on image size and may take up to a few minutes.
</p>
<div id="l"></div>
</div>
<div id="version"></div>
</body>
</html>

View File

@@ -0,0 +1,41 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>GPT update</title>
<link rel="stylesheet" href="/style.css">
<script src="/main.js"></script>
</head>
<body onload="getversion()">
<div id="m">
<h1>GPT UPDATE</h1>
<p id="hint">
You are going to update <strong>GPT (Partition Table)</strong> on the device.<br>
Please, choose file from your local hard drive and click <strong>Upload</strong> button.
</p>
<form id="form">
<input id="file" type="file" name="gpt">
<input type="button" value="Upload" onclick="upload('gpt')">
</form>
<div>
<div class="bar" id="bar" style="display: none; --percent: 0;"></div>
</div>
<div id="size" style="display: none;">Size: xxxx</div>
<div id="md5" style="display: none;">MD5: xxxx</div>
<div id="upgrade" style="display: none;">
<p>If all information above is correct, click "Update".</p>
<button class="button" onclick="location = '/flashing.html'">Update</button>
</div>
<div class="i w">
<strong>WARNINGS</strong>
<ul>
<li>do not power off the device during update</li>
<li>if everything goes well, the device will restart</li>
<li>you can upload whatever you want, so be sure that you choose proper GPT for your device</li>
<li>updating GPT is a dangerous operation and may damage your device!</li>
</ul>
</div>
</div>
<div id="version"></div>
</body>
</html>

View File

@@ -1,19 +1,48 @@
<!doctype html>
<!DOCTYPE HTML>
<html>
<head>
<title>MediaTek System Recovery Mode</title>
<link rel="stylesheet" type="text/css" href="/style.css">
</head>
<body>
<div id="banner">
MediaTek U-Boot System Recovery Mode
</div>
<div id="main">
<p>Upload new firmware:</p>
<form action="/upload" method="post" enctype="multipart/form-data">
<p><input type="file" name="firmware" /></p>
<p><input type="submit" id="submit" value="Upload" /></p>
</form>
</div>
</body>
</html>
<head>
<meta charset="utf-8">
<title>Firmware update</title>
<link rel="stylesheet" href="/style.css">
<script src="/main.js"></script>
</head>
<body onload="startup()">
<div id="m">
<h1>FIRMWARE UPDATE</h1>
<p id="hint">
You are going to update <strong>firmware</strong> on the device.<br>
Please, choose file from your local hard drive and click <strong>Upload</strong> button.
</p>
<form id="form">
<div id="mtd_layout" style="display: none;">
<div id="current_mtd_layout"></div>
<br>
Choose mtd layout:
<select id="mtd_layout_label" name="mtd_layout_label"></select>
<br><br>
</div>
<input id="file" type="file" name="firmware">
<input type="button" value="Upload" onclick="upload('firmware')">
</form>
<div>
<div class="bar" id="bar" style="display: none; --percent: 0;"></div>
</div>
<div id="size" style="display: none;">Size: xxxx</div>
<div id="md5" style="display: none;">MD5: xxxx</div>
<div id="mtd" style="display: none;">MTD layout: xxxx</div>
<div id="upgrade" style="display: none;">
<p>If all information above is correct, click "Update".</p>
<button class="button" onclick="location = '/flashing.html'">Update</button>
</div>
<div class="i w">
<strong>WARNINGS</strong>
<ul>
<li>do not power off the device during update</li>
<li>if everything goes well, the device will restart</li>
<li>you can upload whatever you want, so be sure that you choose proper firmware image for your device</li>
</ul>
</div>
</div>
<div id="version"></div>
</body>
</html>

View File

@@ -0,0 +1,39 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Load initramfs</title>
<link rel="stylesheet" href="/style.css">
<script src="/main.js"></script>
</head>
<body onload="startup()">
<div id="m">
<h1>LOAD INITRAMFS</h1>
<p id="hint">
You are going to load <strong>initramfs</strong> on the device.<br>
Please, choose file from your local hard drive and click <strong>Upload</strong> button.
</p>
<form id="form">
<input id="file" type="file" name="initramfs">
<input type="button" value="Upload" onclick="upload('initramfs')">
</form>
<div>
<div class="bar" id="bar" style="display: none; --percent: 0;"></div>
</div>
<div id="size" style="display: none;">Size: xxxx</div>
<div id="md5" style="display: none;">MD5: xxxx</div>
<div id="upgrade" style="display: none;">
<p>If all information above is correct, click "Boot".</p>
<button class="button" onclick="location = '/booting.html'">Boot</button>
</div>
<div class="i w">
<strong>WARNINGS</strong>
<ul>
<li>if everything goes well, the device will boot into the initramfs</li>
<li>you can upload whatever you want, so be sure that you choose proper initramfs image for your device</li>
</ul>
</div>
</div>
<div id="version"></div>
</body>
</html>

View File

@@ -0,0 +1,119 @@
function ajax(opt) {
var xmlhttp;
if (window.XMLHttpRequest) {
// IE7+, Firefox, Chrome, Opera, Safari
xmlhttp = new XMLHttpRequest();
} else {
// IE6, IE5
xmlhttp = new ActiveXObject('Microsoft.XMLHTTP');
}
xmlhttp.upload.addEventListener('progress', function (e) {
if (opt.progress)
opt.progress(e)
})
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
if (opt.done)
opt.done(xmlhttp.responseText);
}
}
if (opt.timeout)
xmlhttp.timeout = opt.timeout;
var method = 'GET';
if (opt.data)
method = 'POST'
xmlhttp.open(method, opt.url);
xmlhttp.send(opt.data);
}
function startup(){
getversion();
getmtdlayoutlist();
}
function getmtdlayoutlist() {
ajax({
url: '/getmtdlayout',
done: function(mtd_layout_list) {
if (mtd_layout_list == "error")
return;
var mtd_layout = mtd_layout_list.split(';');
document.getElementById('current_mtd_layout').innerHTML = "Current mtd layout: " + mtd_layout[0];
var e = document.getElementById('mtd_layout_label');
for (var i=1; i<mtd_layout.length; i++) {
if (mtd_layout[i].length > 0) {
e.options.add(new Option(mtd_layout[i], mtd_layout[i]));
}
}
document.getElementById('mtd_layout').style.display = '';
}
})
}
function getversion() {
ajax({
url: '/version',
done: function(version) {
document.getElementById('version').innerHTML = version
}
})
}
function upload(name) {
var file = document.getElementById('file').files[0]
if (!file)
return
document.getElementById('form').style.display = 'none';
document.getElementById('hint').style.display = 'none';
var form = new FormData();
form.append(name, file);
var mtd_layout_list = document.getElementById('mtd_layout_label');
if (mtd_layout_list && mtd_layout_list.options.length > 0) {
var mtd_idx = mtd_layout_list.selectedIndex;
form.append("mtd_layout", mtd_layout_list.options[mtd_idx].value);
}
ajax({
url: '/upload',
data: form,
done: function(resp) {
if (resp == 'fail') {
location = '/fail.html';
} else {
const info = resp.split(' ');
document.getElementById('size').style.display = 'block';
document.getElementById('size').innerHTML = 'Size: ' + info[0];
document.getElementById('md5').style.display = 'block';
document.getElementById('md5').innerHTML = 'MD5: ' + info[1];
if (info[2]) {
document.getElementById('mtd').style.display = 'block';
document.getElementById('mtd').innerHTML = 'MTD layout: ' + info[2];
}
document.getElementById('upgrade').style.display = 'block';
}
},
progress: function(e) {
var percentage = parseInt(e.loaded / e.total * 100)
document.getElementById('bar').setAttribute('style', '--percent: ' + percentage);
}
})
}

View File

@@ -1,26 +1,185 @@
h1,
p,
form,
ul {
margin: 0;
padding: 0;
}
html,
body {
padding: 1em;
font: 13px/20px Arial, sans-serif;
background: #EDEDED;
}
#banner {
width: 100%;
height: 40px;
font-size: 2em;
#m {
max-width: 750px;
margin: 30px auto 10px;
border: solid 1px #BABABA;
background: #FFF;
border-radius: 7px;
box-shadow: 0 0 10px #D2D1D1;
}
#m > * {
padding: 20px;
}
h1 {
font: bold 50px/50px Tahoma;
border-bottom: solid 1px #E8E8E8;
}
a,
h1 {
color: #2450AD;
text-decoration: none;
}
.i {
margin: 20px;
border-radius: 7px;
text-align: justify;
}
.w {
background: #FEFDCE;
border: solid 1px #FFC643;
}
.e {
background: #FFE7E7;
border:solid 1px #FE7171;
}
#version {
text-align: center;
margin-bottom: 30px;
}
#main {
width: 500px;
margin: auto;
form,
p,
h1 {
text-align: center;
}
#submit {
ul {
list-style: square;
margin: 0 0 0 20px;
}
.red {
color: #E41616;
}
.i strong {
margin: 0 0 5px;
display: block;
margin: auto;
}
#fileinfo {
padding-left: 20px;
}
#upgrade-btn {
margin: 0 auto;
}
.bar {
height: 20px; width:400px;
background-color: #f5f5f5;
border-radius: 25px;
margin: 0 auto;
}
.bar::before {
counter-reset: progress var(--percent);
content: counter(progress) '%\2002';
display: block;
width: calc(400px * var(--percent) / 100);
font-size: 12px;
color: #fff;
background-color: #2486ff;
text-align: right;
white-space: nowrap;
overflow: hidden;
border-radius: 25px;
}
#md5, #size, #mtd {
font-size: 1.6em;
margin-left: 155px;
}
#upgrade {
text-align: center;
}
#upgrade p {
color: green;
font-size: 2em;
}
.button {
box-shadow: inset 0px -3px 7px 0px #29bbff;
background: linear-gradient(to bottom, #2dabf9 5%, #0688fa 100%);
background-color: #2dabf9;
border-radius: 10px;
border: 1px solid #0b0e07;
color: white;
font-size: 2em;
padding: 9px 23px;
text-shadow: 0px 1px 0px #263666;
margin-top: 10px;
}
.button:hover {
background: linear-gradient(to bottom, #0688fa 5%, #2dabf9 100%);
background-color: #0688fa;
}
#l {
height: 30px;
width: 30px;
margin: 0 auto 20px;
-webkit-animation: r 1s infinite linear;
-moz-animation: r 1s infinite linear;
-o-animation: r 1s infinite linear;
animation: r 1s infinite linear;
border-left: 7px solid #eaf1ff;
border-right: 7px solid #eaf1ff;
border-bottom: 7px solid #eaf1ff;
border-top: 7px solid #2450ad;
border-radius: 100%;
}
@-webkit-keyframes r {
from {
-webkit-transform: rotate(0deg);
}
to {
-webkit-transform: rotate(359deg);
}
}
@-moz-keyframes r {
from {
-moz-transform: rotate(0deg);
}
to {
-moz-transform: rotate(359deg);
}
}
@-o-keyframes r {
from {
-o-transform: rotate(0deg);
}
to {
-o-transform: rotate(359deg);
}
}
@keyframes r {
from {
transform: rotate(0deg);
}
to {
transform: rotate(359deg);
}
}

View File

@@ -1,2 +0,0 @@
<p><strong>Upgrade complete!</strong></p>
<p>Rebooting ...</p>

View File

@@ -0,0 +1,41 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>U-Boot update</title>
<link rel="stylesheet" href="/style.css">
<script src="/main.js"></script>
</head>
<body onload="getversion()">
<div id="m">
<h1>U-BOOT UPDATE</h1>
<p id="hint">
You are going to update <strong>U-Boot (bootloader)</strong> on the device.<br>
Please, choose file from your local hard drive and click <strong>Upload</strong> button.
</p>
<form id="form">
<input id="file" type="file" name="fip">
<input type="button" value="Upload" onclick="upload('fip')">
</form>
<div>
<div class="bar" id="bar" style="display: none; --percent: 0;"></div>
</div>
<div id="size" style="display: none;">Size: xxxx</div>
<div id="md5" style="display: none;">MD5: xxxx</div>
<div id="upgrade" style="display: none;">
<p>If all information above is correct, click "Update".</p>
<button class="button" onclick="location = '/flashing.html'">Update</button>
</div>
<div class="i w">
<strong>WARNINGS</strong>
<ul>
<li>do not power off the device during update</li>
<li>if everything goes well, the device will restart</li>
<li>you can upload whatever you want, so be sure that you choose proper U-Boot image for your device</li>
<li>updating U-Boot is a very dangerous operation and may damage your device!</li>
</ul>
</div>
</div>
<div id="version"></div>
</body>
</html>

View File

@@ -1,23 +0,0 @@
<!doctype html>
<html>
<head>
<title>Confirm - MediaTek System Recovery Mode</title>
<link rel="stylesheet" type="text/css" href="/style.css">
</head>
<body>
<div id="banner">
MediaTek U-Boot System Recovery Mode
</div>
<div id="main">
<p>File confirmation:</p>
<div id="fileinfo">
<p>MD5: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX</p>
<p>Size: YYYYYYYYYY Bytes</p>
</div>
<p>If all information above is correct, click [Proceed].</p>
<form action="/flashing" method="post" enctype="multipart/form-data">
<p><input type="submit" id="submit" value="Proceed" /></p>
</form>
</div>
</body>
</html>

View File

@@ -1,16 +0,0 @@
<!doctype html>
<html>
<head>
<title>Error - MediaTek System Recovery Mode</title>
<link rel="stylesheet" type="text/css" href="/style.css">
</head>
<body>
<div id="banner">
MediaTek U-Boot System Recovery Mode
</div>
<div id="main">
<p><strong>Firmware image verification failed!</strong></p>
<p><input type="button" value="Return" onclick="location='/'" /></p>
</div>
</body>
</html>

View File

@@ -0,0 +1,14 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _FAILSAFE_FW_TYPE_H_
#define _FAILSAFE_FW_TYPE_H_
typedef enum {
FW_TYPE_GPT,
FW_TYPE_BL2,
FW_TYPE_FIP,
FW_TYPE_FW,
FW_TYPE_INITRD,
} failsafe_fw_t;
#endif