mirror of https://github.com/arendst/Tasmota.git
Fix to Partition_Wizard for shelly (#19056)
This commit is contained in:
parent
f462fa772d
commit
f56307e321
|
@ -300,8 +300,8 @@ class Partition_otadata
|
|||
#- load otadata from SPI Flash -#
|
||||
def load()
|
||||
import flash
|
||||
var otadata0 = flash.read(0xE000, 32)
|
||||
var otadata1 = flash.read(0xF000, 32)
|
||||
var otadata0 = flash.read(self.offset, 32)
|
||||
var otadata1 = flash.read(self.offset + 0x1000, 32)
|
||||
self.seq0 = otadata0.get(0, 4) #- ota_seq for block 1 -#
|
||||
self.seq1 = otadata1.get(0, 4) #- ota_seq for block 2 -#
|
||||
var valid0 = otadata0.get(28, 4) == self.crc32_ota_seq(self.seq0) #- is CRC32 valid? -#
|
||||
|
|
|
@ -248,65 +248,68 @@ be_local_closure(Partition_otadata_load, /* name */
|
|||
0, /* has sup protos */
|
||||
NULL, /* no sub protos */
|
||||
1, /* has constants */
|
||||
( &(const bvalue[ 8]) { /* constants */
|
||||
( &(const bvalue[ 9]) { /* constants */
|
||||
/* K0 */ be_nested_str(flash),
|
||||
/* K1 */ be_nested_str(read),
|
||||
/* K2 */ be_nested_str(seq0),
|
||||
/* K3 */ be_nested_str(get),
|
||||
/* K4 */ be_const_int(0),
|
||||
/* K5 */ be_nested_str(seq1),
|
||||
/* K6 */ be_nested_str(crc32_ota_seq),
|
||||
/* K7 */ be_nested_str(_validate),
|
||||
/* K2 */ be_nested_str(offset),
|
||||
/* K3 */ be_nested_str(seq0),
|
||||
/* K4 */ be_nested_str(get),
|
||||
/* K5 */ be_const_int(0),
|
||||
/* K6 */ be_nested_str(seq1),
|
||||
/* K7 */ be_nested_str(crc32_ota_seq),
|
||||
/* K8 */ be_nested_str(_validate),
|
||||
}),
|
||||
&be_const_str_load,
|
||||
&be_const_str_solidified,
|
||||
( &(const binstruction[46]) { /* code */
|
||||
( &(const binstruction[48]) { /* code */
|
||||
0xA4060000, // 0000 IMPORT R1 K0
|
||||
0x8C080301, // 0001 GETMET R2 R1 K1
|
||||
0x5412DFFF, // 0002 LDINT R4 57344
|
||||
0x88100102, // 0002 GETMBR R4 R0 K2
|
||||
0x5416001F, // 0003 LDINT R5 32
|
||||
0x7C080600, // 0004 CALL R2 3
|
||||
0x8C0C0301, // 0005 GETMET R3 R1 K1
|
||||
0x5416EFFF, // 0006 LDINT R5 61440
|
||||
0x541A001F, // 0007 LDINT R6 32
|
||||
0x7C0C0600, // 0008 CALL R3 3
|
||||
0x8C100503, // 0009 GETMET R4 R2 K3
|
||||
0x58180004, // 000A LDCONST R6 K4
|
||||
0x541E0003, // 000B LDINT R7 4
|
||||
0x7C100600, // 000C CALL R4 3
|
||||
0x90020404, // 000D SETMBR R0 K2 R4
|
||||
0x8C100703, // 000E GETMET R4 R3 K3
|
||||
0x58180004, // 000F LDCONST R6 K4
|
||||
0x541E0003, // 0010 LDINT R7 4
|
||||
0x7C100600, // 0011 CALL R4 3
|
||||
0x90020A04, // 0012 SETMBR R0 K5 R4
|
||||
0x8C100503, // 0013 GETMET R4 R2 K3
|
||||
0x541A001B, // 0014 LDINT R6 28
|
||||
0x541E0003, // 0015 LDINT R7 4
|
||||
0x7C100600, // 0016 CALL R4 3
|
||||
0x8C140106, // 0017 GETMET R5 R0 K6
|
||||
0x881C0102, // 0018 GETMBR R7 R0 K2
|
||||
0x7C140400, // 0019 CALL R5 2
|
||||
0x1C100805, // 001A EQ R4 R4 R5
|
||||
0x8C140703, // 001B GETMET R5 R3 K3
|
||||
0x541E001B, // 001C LDINT R7 28
|
||||
0x54220003, // 001D LDINT R8 4
|
||||
0x7C140600, // 001E CALL R5 3
|
||||
0x8C180106, // 001F GETMET R6 R0 K6
|
||||
0x88200105, // 0020 GETMBR R8 R0 K5
|
||||
0x7C180400, // 0021 CALL R6 2
|
||||
0x1C140A06, // 0022 EQ R5 R5 R6
|
||||
0x5C180800, // 0023 MOVE R6 R4
|
||||
0x741A0001, // 0024 JMPT R6 #0027
|
||||
0x4C180000, // 0025 LDNIL R6
|
||||
0x90020406, // 0026 SETMBR R0 K2 R6
|
||||
0x5C180A00, // 0027 MOVE R6 R5
|
||||
0x741A0001, // 0028 JMPT R6 #002B
|
||||
0x4C180000, // 0029 LDNIL R6
|
||||
0x90020A06, // 002A SETMBR R0 K5 R6
|
||||
0x8C180107, // 002B GETMET R6 R0 K7
|
||||
0x7C180200, // 002C CALL R6 1
|
||||
0x80000000, // 002D RET 0
|
||||
0x88140102, // 0006 GETMBR R5 R0 K2
|
||||
0x541A0FFF, // 0007 LDINT R6 4096
|
||||
0x00140A06, // 0008 ADD R5 R5 R6
|
||||
0x541A001F, // 0009 LDINT R6 32
|
||||
0x7C0C0600, // 000A CALL R3 3
|
||||
0x8C100504, // 000B GETMET R4 R2 K4
|
||||
0x58180005, // 000C LDCONST R6 K5
|
||||
0x541E0003, // 000D LDINT R7 4
|
||||
0x7C100600, // 000E CALL R4 3
|
||||
0x90020604, // 000F SETMBR R0 K3 R4
|
||||
0x8C100704, // 0010 GETMET R4 R3 K4
|
||||
0x58180005, // 0011 LDCONST R6 K5
|
||||
0x541E0003, // 0012 LDINT R7 4
|
||||
0x7C100600, // 0013 CALL R4 3
|
||||
0x90020C04, // 0014 SETMBR R0 K6 R4
|
||||
0x8C100504, // 0015 GETMET R4 R2 K4
|
||||
0x541A001B, // 0016 LDINT R6 28
|
||||
0x541E0003, // 0017 LDINT R7 4
|
||||
0x7C100600, // 0018 CALL R4 3
|
||||
0x8C140107, // 0019 GETMET R5 R0 K7
|
||||
0x881C0103, // 001A GETMBR R7 R0 K3
|
||||
0x7C140400, // 001B CALL R5 2
|
||||
0x1C100805, // 001C EQ R4 R4 R5
|
||||
0x8C140704, // 001D GETMET R5 R3 K4
|
||||
0x541E001B, // 001E LDINT R7 28
|
||||
0x54220003, // 001F LDINT R8 4
|
||||
0x7C140600, // 0020 CALL R5 3
|
||||
0x8C180107, // 0021 GETMET R6 R0 K7
|
||||
0x88200106, // 0022 GETMBR R8 R0 K6
|
||||
0x7C180400, // 0023 CALL R6 2
|
||||
0x1C140A06, // 0024 EQ R5 R5 R6
|
||||
0x5C180800, // 0025 MOVE R6 R4
|
||||
0x741A0001, // 0026 JMPT R6 #0029
|
||||
0x4C180000, // 0027 LDNIL R6
|
||||
0x90020606, // 0028 SETMBR R0 K3 R6
|
||||
0x5C180A00, // 0029 MOVE R6 R5
|
||||
0x741A0001, // 002A JMPT R6 #002D
|
||||
0x4C180000, // 002B LDNIL R6
|
||||
0x90020C06, // 002C SETMBR R0 K6 R6
|
||||
0x8C180108, // 002D GETMET R6 R0 K8
|
||||
0x7C180200, // 002E CALL R6 1
|
||||
0x80000000, // 002F RET 0
|
||||
})
|
||||
)
|
||||
);
|
||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -24,25 +24,49 @@ class Partition_wizard_UI
|
|||
|
||||
if persist.find("factory_migrate") == true
|
||||
# remove marker to avoid bootloop if something goes wrong
|
||||
tasmota.log("UPL: Resuming after step 1", 2)
|
||||
persist.remove("factory_migrate")
|
||||
persist.save()
|
||||
|
||||
# continue the migration process 5 seconds after Wifi is connected
|
||||
def continue_after_5s()
|
||||
tasmota.remove_rule("parwiz_5s") # first remove rule to avoid firing it again at Wifi reconnect
|
||||
tasmota.remove_rule("parwiz_5s1") # first remove rule to avoid firing it again at Wifi reconnect
|
||||
tasmota.remove_rule("parwiz_5s2") # first remove rule to avoid firing it again at Wifi reconnect
|
||||
tasmota.set_timer(5000, /-> self.do_safeboot_partitioning()) # delay by 5 s
|
||||
end
|
||||
tasmota.add_rule("Wifi#Connected=1", continue_after_5s, "parwiz_5s")
|
||||
tasmota.add_rule("Wifi#Connected=1", continue_after_5s, "parwiz_5s1")
|
||||
tasmota.add_rule("Wifi#Connected==1", continue_after_5s, "parwiz_5s2")
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
# Patch partition core since we can't chang the solidified code
|
||||
# ----------------------------------------------------------------------
|
||||
def patch_partition_core(p)
|
||||
var otadata = p.otadata
|
||||
|
||||
# patch load
|
||||
import flash
|
||||
var otadata0 = flash.read(otadata.offset, 32)
|
||||
var otadata1 = flash.read(otadata.offset + 0x1000, 32)
|
||||
otadata.seq0 = otadata0.get(0, 4) #- ota_seq for block 1 -#
|
||||
otadata.seq1 = otadata1.get(0, 4) #- ota_seq for block 2 -#
|
||||
var valid0 = otadata0.get(28, 4) == otadata.crc32_ota_seq(otadata.seq0) #- is CRC32 valid? -#
|
||||
var valid1 = otadata1.get(28, 4) == otadata.crc32_ota_seq(otadata.seq1) #- is CRC32 valid? -#
|
||||
if !valid0 otadata.seq0 = nil end
|
||||
if !valid1 otadata.seq1 = nil end
|
||||
|
||||
otadata._validate()
|
||||
end
|
||||
|
||||
def default_safeboot_URL()
|
||||
import string
|
||||
var arch_sub = tasmota.arch()
|
||||
if arch_sub[0..4] == "esp32"
|
||||
arch_sub = arch_sub[5..] # get the esp32 variant
|
||||
end
|
||||
return format(self._default_safeboot_URL, arch_sub)
|
||||
return string.format(self._default_safeboot_URL, arch_sub)
|
||||
end
|
||||
|
||||
# create a method for adding a button to the main menu
|
||||
|
@ -53,15 +77,34 @@ class Partition_wizard_UI
|
|||
"<form id=but_part_mgr style='display: block;' action='part_wiz' method='get'><button>Partition Wizard</button></form><p></p>")
|
||||
end
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
# Get last fs
|
||||
#
|
||||
# Get the last fs partition
|
||||
# Return the actual slot
|
||||
# ----------------------------------------------------------------------
|
||||
def get_last_fs(p)
|
||||
var sz = size(p.slots)
|
||||
var idx = 1
|
||||
while idx < sz
|
||||
var slot = p.slots[-idx]
|
||||
if slot.is_spiffs()
|
||||
return slot
|
||||
end
|
||||
idx += 1
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
#- ---------------------------------------------------------------------- -#
|
||||
#- Get fs unallocated size
|
||||
#- ---------------------------------------------------------------------- -#
|
||||
def get_unallocated_k(p)
|
||||
var last_slot = p.slots[-1]
|
||||
if last_slot.is_spiffs()
|
||||
var last_fs = self.get_last_fs(p)
|
||||
if last_fs != nil
|
||||
# verify that last slot is filesystem
|
||||
var flash_size_k = self.get_max_flash_size_k(p)
|
||||
var partition_end_k = (last_slot.start + last_slot.sz) / 1024 # last kb used for fs
|
||||
var partition_end_k = (last_fs.start + last_fs.sz) / 1024 # last kb used for fs
|
||||
if partition_end_k < flash_size_k
|
||||
return flash_size_k - partition_end_k
|
||||
end
|
||||
|
@ -73,8 +116,8 @@ class Partition_wizard_UI
|
|||
#- Get max fs start address when expanded to maximum
|
||||
#- ---------------------------------------------------------------------- -#
|
||||
def get_max_fs_start_k(p)
|
||||
var last_slot = p.slots[-1]
|
||||
if last_slot.is_spiffs() # verify that last slot is filesystem
|
||||
var last_fs = p.slots[-1]
|
||||
if last_fs != nil # verify that last slot is filesystem
|
||||
# get end of previous partition slot
|
||||
var last_app = p.slots[-2]
|
||||
# round upper 64kB
|
||||
|
@ -85,7 +128,7 @@ class Partition_wizard_UI
|
|||
end
|
||||
|
||||
#- ---------------------------------------------------------------------- -#
|
||||
#- Get max falsh size
|
||||
#- Get max flash size
|
||||
#
|
||||
# Takes into account that the flash size written may not be accurate
|
||||
# and the flash chip may be larger
|
||||
|
@ -99,15 +142,40 @@ class Partition_wizard_UI
|
|||
return flash_size_k
|
||||
end
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
# Remove any non wanted partion after last FS
|
||||
# ----------------------------------------------------------------------
|
||||
def remove_partition_after_last_fs(p)
|
||||
# remove any partition after last fs
|
||||
do
|
||||
var last_fs = self.get_last_fs(p)
|
||||
var changed = false
|
||||
if last_fs != nil
|
||||
while true
|
||||
var last_slot = p.slots[-1]
|
||||
if !last_slot.is_spiffs() && (last_slot.type != 0)
|
||||
p.slots.remove(size(p.slots) - 1) # remove last slot
|
||||
changed = true
|
||||
else
|
||||
break
|
||||
end
|
||||
end
|
||||
if changed p.save() end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
#- ---------------------------------------------------------------------- -#
|
||||
#- Resize flash definition if needed
|
||||
#- ---------------------------------------------------------------------- -#
|
||||
def resize_max_flash_size_k(p)
|
||||
self.remove_partition_after_last_fs(p)
|
||||
var flash_size_k = tasmota.memory()['flash']
|
||||
var flash_size_real_k = tasmota.memory().find("flash_real", flash_size_k)
|
||||
var flash_definition_sector = self.get_flash_definition_sector(p)
|
||||
if (flash_size_k != flash_size_real_k) && flash_definition_sector != nil
|
||||
import flash
|
||||
import string
|
||||
|
||||
flash_size_k = flash_size_real_k # try to expand the flash size definition
|
||||
|
||||
|
@ -131,7 +199,7 @@ class Partition_wizard_UI
|
|||
var old_def = flash_def[3]
|
||||
flash_def[3] = (flash_def[3] & 0x0F) | flash_size_code
|
||||
flash.write(flash_definition_sector, flash_def)
|
||||
tasmota.log(format("UPL: changing flash definition from 0x02X to 0x%02X", old_def, flash_def[3]), 3)
|
||||
tasmota.log(string.format("UPL: changing flash definition from 0x02X to 0x%02X", old_def, flash_def[3]), 3)
|
||||
else
|
||||
raise "internal_error", "wrong flash size "+str(flash_size_real_m)
|
||||
end
|
||||
|
@ -142,9 +210,9 @@ class Partition_wizard_UI
|
|||
#- Get current fs size
|
||||
#- ---------------------------------------------------------------------- -#
|
||||
def get_cur_fs_size_k(p)
|
||||
var last_slot = p.slots[-1]
|
||||
if last_slot.is_spiffs() # verify that last slot is filesystem
|
||||
return (last_slot.sz + 1023) / 1024
|
||||
var last_fs = p.slots[-1]
|
||||
if last_fs != nil
|
||||
return (last_fs.sz + 1023) / 1024
|
||||
end
|
||||
return 0
|
||||
end
|
||||
|
@ -171,13 +239,14 @@ class Partition_wizard_UI
|
|||
#- ---------------------------------------------------------------------- -#
|
||||
def show_resize_fs(p)
|
||||
import webserver
|
||||
import string
|
||||
var unallocated = self.get_unallocated_k(p)
|
||||
|
||||
# if there is unallocated space, propose only to claim it
|
||||
if unallocated > 0
|
||||
webserver.content_send("<fieldset><legend><b> Resize FS to max </b></legend><p></p>")
|
||||
|
||||
webserver.content_send(format("<p>You can expand the file system by %i KB.<br>Its content will be lost.</p>", unallocated))
|
||||
webserver.content_send(string.format("<p>You can expand the file system by %i KB.<br>Its content will be lost.</p>", unallocated))
|
||||
|
||||
webserver.content_send("<form action='/part_wiz' method='post' ")
|
||||
webserver.content_send("onsubmit='return confirm(\"This will DELETE the content of the file system and cause a restart.\");'>")
|
||||
|
@ -190,7 +259,7 @@ class Partition_wizard_UI
|
|||
var flash_size_k = self.get_max_flash_size_k()
|
||||
var fs_max_size_k = flash_size_k - max_fs_start_k
|
||||
var current_fs_size_k = self.get_cur_fs_size_k(p)
|
||||
#print(format(">>> max_fs_start_k=0x%X flash_size_k=0x%X fs_max_size_k=%i current_fs_size_k=%i", max_fs_start_k, flash_size_k, fs_max_size_k, current_fs_size_k))
|
||||
#print(string.format(">>> max_fs_start_k=0x%X flash_size_k=0x%X fs_max_size_k=%i current_fs_size_k=%i", max_fs_start_k, flash_size_k, fs_max_size_k, current_fs_size_k))
|
||||
|
||||
if max_fs_start_k > 0 && fs_max_size_k > 64
|
||||
webserver.content_send("<fieldset><legend><b> Resize FS </b></legend><p></p>")
|
||||
|
@ -199,7 +268,7 @@ class Partition_wizard_UI
|
|||
|
||||
webserver.content_send("<form action='/part_wiz' method='post' ")
|
||||
webserver.content_send("onsubmit='return confirm(\"This will DELETE the content of the file system and cause a restart.\");'>")
|
||||
webserver.content_send(format("<input type='number' min='64' max='%d' step='64' name='fs_size' value='%i'>", fs_max_size_k, current_fs_size_k))
|
||||
webserver.content_send(string.format("<input type='number' min='64' max='%d' step='64' name='fs_size' value='%i'>", fs_max_size_k, current_fs_size_k))
|
||||
webserver.content_send("<p></p><button name='resize_fs' class='button bred'>Resize FS</button></form></p>")
|
||||
|
||||
webserver.content_send("<p></p></fieldset><p></p>")
|
||||
|
@ -231,7 +300,7 @@ class Partition_wizard_UI
|
|||
def factory_migrate_eligible(p)
|
||||
if p.ota_max() <= 0 return false end # device does not have 2x OTA
|
||||
if p.get_factory_slot() != nil return false end
|
||||
if !p.slots[-1].is_spiffs() return false end
|
||||
if self.get_last_fs(p) == nil return false end
|
||||
return true # device does not have factory partition
|
||||
end
|
||||
|
||||
|
@ -254,11 +323,12 @@ class Partition_wizard_UI
|
|||
# - true if DONE
|
||||
# - string if ERROR, indicating the error
|
||||
def test_step_1(p)
|
||||
import string
|
||||
if !self.factory_migrate_eligible(p) return "not eligible to migration" end
|
||||
|
||||
var cur_part = p.otadata.active_otadata # -1=factory 0=ota_0 1=ota_1...
|
||||
if cur_part == 1 return true end
|
||||
if cur_part != 0 return format("active_otadata=%i", cur_part) end # unsupported configuration
|
||||
if cur_part != 0 return string.format("active_otadata=%i", cur_part) end # unsupported configuration
|
||||
# current partition is `app0`
|
||||
# get size of firmware in `app0` and check if it fits on `app1`
|
||||
var app0 = p.get_ota_slot(0)
|
||||
|
@ -314,6 +384,7 @@ class Partition_wizard_UI
|
|||
# `app0` changed subtype to `factory`
|
||||
# `app1` moved to right after `factory` and resized
|
||||
# `app1` changed subtype to `app0` and renamed `app0`
|
||||
# remove any partition past the last fs
|
||||
#
|
||||
# Returns:
|
||||
# - false if READY
|
||||
|
@ -345,10 +416,11 @@ class Partition_wizard_UI
|
|||
|
||||
static def copy_ota(from_addr, to_addr, sz)
|
||||
import flash
|
||||
import string
|
||||
var size_left = sz
|
||||
var offset = 0
|
||||
|
||||
tasmota.log(format("UPL: Copy flash from 0x%06X to 0x%06X (size: %ikB)", from_addr, to_addr, sz / 1024), 2)
|
||||
tasmota.log(string.format("UPL: Copy flash from 0x%06X to 0x%06X (size: %ikB)", from_addr, to_addr, sz / 1024), 2)
|
||||
while size_left > 0
|
||||
var b = flash.read(from_addr + offset, 4096)
|
||||
flash.erase(to_addr + offset, 4096)
|
||||
|
@ -356,13 +428,14 @@ class Partition_wizard_UI
|
|||
size_left -= 4096
|
||||
offset += 4096
|
||||
if ((offset-4096) / 102400) < (offset / 102400)
|
||||
tasmota.log(format("UPL: Progress %ikB", offset/1024), 3)
|
||||
tasmota.log(string.format("UPL: Progress %ikB", offset/1024), 3)
|
||||
end
|
||||
end
|
||||
tasmota.log("UPL: done", 2)
|
||||
end
|
||||
|
||||
def do_step_1(p)
|
||||
import persist
|
||||
var step1_state = self.test_step_1(p)
|
||||
if step1_state == true return true end
|
||||
if type(step1_state) == 'string)' raise "internal_error", step1_state end
|
||||
|
@ -377,11 +450,15 @@ class Partition_wizard_UI
|
|||
p.set_active(1)
|
||||
p.save()
|
||||
|
||||
persist.factory_migrate = true
|
||||
persist.save()
|
||||
|
||||
tasmota.log("UPL: restarting on `app1`", 2)
|
||||
tasmota.cmd("Restart 1")
|
||||
end
|
||||
|
||||
def do_step_2(p, safeboot_url)
|
||||
import string
|
||||
if safeboot_url == nil || safeboot_url == ""
|
||||
safeboot_url = self.default_safeboot_URL()
|
||||
tasmota.log("UPL: no `safeboot` URL, defaulting to "+safeboot_url, 2)
|
||||
|
@ -399,7 +476,7 @@ class Partition_wizard_UI
|
|||
var safeboot_size = cl.get_size()
|
||||
if safeboot_size <= 500000 raise "internal_error", "wrong safeboot size "+str(safeboot_size) end
|
||||
if safeboot_size > (self.app_size_min * 1024) raise "internal_error", "safeboot is too large "+str(safeboot_size / 1024)+"kB" end
|
||||
tasmota.log(format("UPL: flashing `safeboot` from %s %ikB", safeboot_url, (safeboot_size / 1024) + 1), 2)
|
||||
tasmota.log(string.format("UPL: flashing `safeboot` from %s %ikB", safeboot_url, (safeboot_size / 1024) + 1), 2)
|
||||
var app0 = p.get_ota_slot(0)
|
||||
if app0.start != 0x10000 raise "internal_error", "`app0` offset is not 0x10000" end
|
||||
cl.write_flash(app0.start)
|
||||
|
@ -415,6 +492,9 @@ class Partition_wizard_UI
|
|||
if step3_state == true return true end
|
||||
if type(step3_state) == 'string' raise "internal_error", step3_state end
|
||||
|
||||
# remove any partition after last fs
|
||||
self.remove_partition_after_last_fs(p)
|
||||
|
||||
var app0 = p.get_ota_slot(0)
|
||||
var app1 = p.get_ota_slot(1)
|
||||
if app0 == nil || app1 == nil raise "internal_error", "there are no `app0` or `app1` partitions" end
|
||||
|
@ -479,6 +559,7 @@ class Partition_wizard_UI
|
|||
def show_migrate_to_factory(p)
|
||||
# display ota partitions
|
||||
import webserver
|
||||
import string
|
||||
|
||||
if !self.factory_migrate_eligible(p) return end
|
||||
|
||||
|
@ -488,20 +569,20 @@ class Partition_wizard_UI
|
|||
webserver.content_send("<p>Please see <a href='https://tasmota.github.io/docs/Safeboot/' target='_blank'>Safeboot layout documentation</a></p>")
|
||||
webserver.content_send("<p> </p>")
|
||||
|
||||
webserver.content_send(format("<p>Step 1: %s</p>", self.display_step_state(self.test_step_1(p), "boot on `app1`")))
|
||||
webserver.content_send(format("<p>Step 2: %s</p>", self.display_step_state(self.test_step_2(p), "flash `safeboot` to `app0`")))
|
||||
webserver.content_send(format("<p>Step 3: %s</p>", self.display_step_state(self.test_step_3(p), "change partition map")))
|
||||
webserver.content_send(format("<p>Step 4: %s</p>", self.display_step_state(self.test_step_4(p), "flash final firmware")))
|
||||
webserver.content_send(string.format("<p>Step 1: %s</p>", self.display_step_state(self.test_step_1(p), "boot on `app1`")))
|
||||
webserver.content_send(string.format("<p>Step 2: %s</p>", self.display_step_state(self.test_step_2(p), "flash `safeboot` to `app0`")))
|
||||
webserver.content_send(string.format("<p>Step 3: %s</p>", self.display_step_state(self.test_step_3(p), "change partition map")))
|
||||
webserver.content_send(string.format("<p>Step 4: %s</p>", self.display_step_state(self.test_step_4(p), "flash final firmware")))
|
||||
|
||||
webserver.content_send("<form action='/part_wiz' method='post' ")
|
||||
webserver.content_send("onsubmit='return confirm(\"This will causes multiple restarts.\");'>")
|
||||
var ota_url = tasmota.cmd("OtaUrl").find("OtaUrl", "")
|
||||
webserver.content_send(format("<br><b>OTA Url</b><br><input id='o1' placeholder='OTA_URL' value='%s'><br>",
|
||||
webserver.content_send(string.format("<br><b>OTA Url</b><br><input id='o1' placeholder='OTA_URL' value='%s'><br>",
|
||||
ota_url))
|
||||
|
||||
import persist
|
||||
var safeboot_url = persist.find("safeboot_url", self.default_safeboot_URL())
|
||||
webserver.content_send(format("<br><b>SAFEBOOT Url</b> (don't change)<input id='o2' placeholder='SAFEBOOT_URL' value='%s'><br>",
|
||||
webserver.content_send(string.format("<br><b>SAFEBOOT Url</b> (don't change)<input id='o2' placeholder='SAFEBOOT_URL' value='%s'><br>",
|
||||
safeboot_url))
|
||||
|
||||
webserver.content_send("<p></p><button name='factory' class='button bred'>Start migration</button></form></p>")
|
||||
|
@ -515,6 +596,7 @@ class Partition_wizard_UI
|
|||
def show_current_partitions(p)
|
||||
# display ota partitions
|
||||
import webserver
|
||||
import string
|
||||
var cur_part = p.otadata.active_otadata # -1=factory 0=ota_0 1=ota_1...
|
||||
|
||||
webserver.content_send("<fieldset><legend><b> Current partitions </b></legend><p></p><table>")
|
||||
|
@ -531,22 +613,22 @@ class Partition_wizard_UI
|
|||
var usage_str = "unknown"
|
||||
var used = slot.get_image_size()
|
||||
if (used >= 0) && (used <= slot.sz)
|
||||
usage_str = format("used %i%%", ((used / 1024) * 100) / (slot.sz / 1024))
|
||||
usage_str = string.format("used %i%%", ((used / 1024) * 100) / (slot.sz / 1024))
|
||||
end
|
||||
var title = format("%ssubtype:%s offset:0x%06X size:0x%06X", current_boot_partition ? "booted " : "", slot.subtype_to_string(), slot.start, slot.sz)
|
||||
var title = string.format("%ssubtype:%s offset:0x%06X size:0x%06X", current_boot_partition ? "booted " : "", slot.subtype_to_string(), slot.start, slot.sz)
|
||||
var col_before = ""
|
||||
var col_after = ""
|
||||
if current_boot_partition
|
||||
col_before = "<span style='color:#0F0'>["
|
||||
col_after = "]</span>"
|
||||
end
|
||||
# webserver.content_send(format("<p><b>%s</b> [%s]: %i KB (%s)</p>", slot.label, slot.subtype_to_string(), slot.size / 1024, usage_str))
|
||||
webserver.content_send(format("<tr><td title='%s'><b>%s%s%s</b>: </td><td align='right'> %i KB </td><td> (%s)</td></tr>",
|
||||
# webserver.content_send(string.format("<p><b>%s</b> [%s]: %i KB (%s)</p>", slot.label, slot.subtype_to_string(), slot.size / 1024, usage_str))
|
||||
webserver.content_send(string.format("<tr><td title='%s'><b>%s%s%s</b>: </td><td align='right'> %i KB </td><td> (%s)</td></tr>",
|
||||
title, col_before, slot.label, col_after, slot.sz / 1024, usage_str))
|
||||
elif slot.is_spiffs()
|
||||
# spiffs partition
|
||||
var title = format("subtype:%s offset:0x%06X size:0x%06X", slot.subtype_to_string(), slot.start, slot.sz)
|
||||
webserver.content_send(format("<tr><td title='%s'><b>fs</b>: </td><td align='right'> %i KB</td></tr>", title, slot.sz / 1024))
|
||||
var title = string.format("subtype:%s offset:0x%06X size:0x%06X", slot.subtype_to_string(), slot.start, slot.sz)
|
||||
webserver.content_send(string.format("<tr><td title='%s'><b>fs</b>: </td><td align='right'> %i KB</td></tr>", title, slot.sz / 1024))
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -555,7 +637,7 @@ class Partition_wizard_UI
|
|||
var last_slot = p.slots[-1]
|
||||
# verify that last slot is file-system
|
||||
var partition_end_k = (last_slot.start + last_slot.sz) / 1024 # last kb used for fs
|
||||
webserver.content_send(format("<tr><td title='offset:0x%06X size:0x%06X'><free>: </td><td align='right'> %i KB</td></tr>",
|
||||
webserver.content_send(string.format("<tr><td title='offset:0x%06X size:0x%06X'><free>: </td><td align='right'> %i KB</td></tr>",
|
||||
partition_end_k * 1024, unallocated * 1024, unallocated))
|
||||
end
|
||||
webserver.content_send("</table>")
|
||||
|
@ -577,6 +659,7 @@ class Partition_wizard_UI
|
|||
import partition_core
|
||||
if !webserver.check_privileged_access() return nil end
|
||||
var p = partition_core.Partition() # load partition layout
|
||||
self.patch_partition_core(p)
|
||||
|
||||
webserver.content_start("Partition Wizard") #- title of the web page -#
|
||||
webserver.content_send_style() #- send standard Tasmota styles -#
|
||||
|
@ -601,6 +684,7 @@ class Partition_wizard_UI
|
|||
#######################################################################
|
||||
def page_part_ctl()
|
||||
import webserver
|
||||
import string
|
||||
if !webserver.check_privileged_access() return nil end
|
||||
|
||||
import partition_core
|
||||
|
@ -609,6 +693,7 @@ class Partition_wizard_UI
|
|||
|
||||
#- check that the partition is valid -#
|
||||
var p = partition_core.Partition()
|
||||
self.patch_partition_core(p)
|
||||
|
||||
try
|
||||
|
||||
|
@ -647,7 +732,7 @@ class Partition_wizard_UI
|
|||
var current_fs_size_k = self.get_cur_fs_size_k(p)
|
||||
|
||||
var fs_target = int(webserver.arg("fs_size"))
|
||||
if (fs_target < 64) || (fs_target > fs_max_size_k) raise "value_error", format("Invalid FS #%d", fs_target) end
|
||||
if (fs_target < 64) || (fs_target > fs_max_size_k) raise "value_error", string.format("Invalid FS #%d", fs_target) end
|
||||
|
||||
# apply the change
|
||||
# shrink last OTA App
|
||||
|
@ -685,12 +770,12 @@ class Partition_wizard_UI
|
|||
raise "value_error", "Unknown command"
|
||||
end
|
||||
except .. as e, m
|
||||
tasmota.log(format("BRY: Exception> '%s' - %s", e, m), 2)
|
||||
tasmota.log(string.format("BRY: Exception> '%s' - %s", e, m), 2)
|
||||
#- display error page -#
|
||||
webserver.content_start("Parameter error") #- title of the web page -#
|
||||
webserver.content_send_style() #- send standard Tasmota styles -#
|
||||
|
||||
webserver.content_send(format("<p style='width:340px;'><b>Exception:</b><br>'%s'<br>%s</p>", e, m))
|
||||
webserver.content_send(string.format("<p style='width:340px;'><b>Exception:</b><br>'%s'<br>%s</p>", e, m))
|
||||
# webserver.content_send("<p></p></fieldset><p></p>")
|
||||
|
||||
webserver.content_button(webserver.BUTTON_MANAGEMENT) #- button back to management page -#
|
||||
|
@ -710,24 +795,23 @@ class Partition_wizard_UI
|
|||
def do_safeboot_partitioning()
|
||||
import webserver
|
||||
import partition_core
|
||||
import string
|
||||
|
||||
var p = partition_core.Partition() # load partition layout
|
||||
self.patch_partition_core(p)
|
||||
if !self.factory_migrate_eligible(p) return true end
|
||||
|
||||
# STEP 1
|
||||
var step1_state = self.test_step_1(p)
|
||||
if type(step1_state) == 'string' return step1_state end
|
||||
if step1_state == false
|
||||
import persist
|
||||
tasmota.log("UPL: Starting step 1", 2)
|
||||
try
|
||||
self.do_step_1(p)
|
||||
except .. as e, m
|
||||
tasmota.log(format("UPL: error (%s) %s", e, m), 2)
|
||||
tasmota.log(string.format("UPL: error (%s) %s", e, m), 2)
|
||||
return m
|
||||
end
|
||||
persist.factory_migrate = true
|
||||
persist.save()
|
||||
return false
|
||||
end
|
||||
tasmota.log("UPL: Step 1 Done", 2)
|
||||
|
@ -742,7 +826,7 @@ class Partition_wizard_UI
|
|||
try
|
||||
self.do_step_2(p, safeboot_url)
|
||||
except .. as e, m
|
||||
tasmota.log(format("UPL: error (%s) %s", e, m), 2)
|
||||
tasmota.log(string.format("UPL: error (%s) %s", e, m), 2)
|
||||
return m
|
||||
end
|
||||
end
|
||||
|
@ -756,7 +840,7 @@ class Partition_wizard_UI
|
|||
try
|
||||
self.do_step_3(p)
|
||||
except .. as e, m
|
||||
tasmota.log(format("UPL: error (%s) %s", e, m), 2)
|
||||
tasmota.log(string.format("UPL: error (%s) %s", e, m), 2)
|
||||
return m
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue