Berry rename solidified partition to partition_core (#15482)

* Berry rename solidified partition to partition_core

* Add init to force `partition_core` as global
This commit is contained in:
s-hadinger 2022-04-29 12:03:19 +02:00 committed by GitHub
parent 77d94c429f
commit 950933cafa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 157 additions and 468 deletions

View File

@ -46,7 +46,7 @@ be_extern_native_module(hue_ntv);
be_extern_native_module(hue_bridge); be_extern_native_module(hue_bridge);
be_extern_native_module(uuid); be_extern_native_module(uuid);
be_extern_native_module(animate); be_extern_native_module(animate);
be_extern_native_module(partition); be_extern_native_module(partition_core);
be_extern_native_module(crc); be_extern_native_module(crc);
#ifdef USE_LVGL #ifdef USE_LVGL
be_extern_native_module(lv); be_extern_native_module(lv);
@ -148,7 +148,7 @@ BERRY_LOCAL const bntvmodule* const be_module_table[] = {
&be_native_module(webserver), &be_native_module(webserver),
#endif // USE_WEBSERVER #endif // USE_WEBSERVER
&be_native_module(flash), &be_native_module(flash),
&be_native_module(partition), &be_native_module(partition_core),
&be_native_module(crc), &be_native_module(crc),
/* user-defined modules register end */ /* user-defined modules register end */

View File

@ -699,7 +699,7 @@ extern const bcstring be_const_str_page_autoconf_ctl;
extern const bcstring be_const_str_page_autoconf_mgr; extern const bcstring be_const_str_page_autoconf_mgr;
extern const bcstring be_const_str_param; extern const bcstring be_const_str_param;
extern const bcstring be_const_str_parse; extern const bcstring be_const_str_parse;
extern const bcstring be_const_str_partition; extern const bcstring be_const_str_partition_core;
extern const bcstring be_const_str_path; extern const bcstring be_const_str_path;
extern const bcstring be_const_str_pc; extern const bcstring be_const_str_pc;
extern const bcstring be_const_str_pc_abs; extern const bcstring be_const_str_pc_abs;

View File

@ -691,7 +691,7 @@ be_define_const_str(page_autoconf_ctl, "page_autoconf_ctl", 2453381496u, 0, 17,
be_define_const_str(page_autoconf_mgr, "page_autoconf_mgr", 3643937031u, 0, 17, &be_const_str_pixel_size); be_define_const_str(page_autoconf_mgr, "page_autoconf_mgr", 3643937031u, 0, 17, &be_const_str_pixel_size);
be_define_const_str(param, "param", 1309554226u, 0, 5, &be_const_str_super); be_define_const_str(param, "param", 1309554226u, 0, 5, &be_const_str_super);
be_define_const_str(parse, "parse", 1111180012u, 0, 5, NULL); be_define_const_str(parse, "parse", 1111180012u, 0, 5, NULL);
be_define_const_str(partition, "partition", 3641267209u, 0, 9, &be_const_str_set_mode_ct); be_define_const_str(partition_core, "partition_core", 2913046901u, 0, 14, &be_const_str_set_bits_per_sample);
be_define_const_str(path, "path", 2223459638u, 0, 4, &be_const_str_remove_rule); be_define_const_str(path, "path", 2223459638u, 0, 4, &be_const_str_remove_rule);
be_define_const_str(pc, "pc", 1313756516u, 0, 2, NULL); be_define_const_str(pc, "pc", 1313756516u, 0, 2, NULL);
be_define_const_str(pc_abs, "pc_abs", 920256495u, 0, 6, &be_const_str_signal_arcs); be_define_const_str(pc_abs, "pc_abs", 920256495u, 0, 6, &be_const_str_signal_arcs);
@ -1291,7 +1291,7 @@ static const bstring* const m_string_table[] = {
(const bstring *)&be_const_str_id_X20must_X20be_X20of_X20type_X20_X27int_X27, (const bstring *)&be_const_str_id_X20must_X20be_X20of_X20type_X20_X27int_X27,
(const bstring *)&be_const_str_autorun, (const bstring *)&be_const_str_autorun,
NULL, NULL,
(const bstring *)&be_const_str_partition, (const bstring *)&be_const_str_set_mode_ct,
(const bstring *)&be_const_str_is_ota, (const bstring *)&be_const_str_is_ota,
NULL, NULL,
(const bstring *)&be_const_str_is_first_time, (const bstring *)&be_const_str_is_first_time,
@ -1403,7 +1403,7 @@ static const bstring* const m_string_table[] = {
NULL, NULL,
(const bstring *)&be_const_str_init, (const bstring *)&be_const_str_init,
NULL, NULL,
(const bstring *)&be_const_str_set_bits_per_sample, (const bstring *)&be_const_str_partition_core,
(const bstring *)&be_const_str_count, (const bstring *)&be_const_str_count,
(const bstring *)&be_const_str__X21_X3D, (const bstring *)&be_const_str__X21_X3D,
NULL, NULL,

View File

@ -504,7 +504,7 @@ be_local_closure(Partition_load_otadata, /* name */
/* K6 */ be_nested_str(start), /* K6 */ be_nested_str(start),
/* K7 */ be_nested_str(stop_iteration), /* K7 */ be_nested_str(stop_iteration),
/* K8 */ be_nested_str(otadata), /* K8 */ be_nested_str(otadata),
/* K9 */ be_nested_str(partition), /* K9 */ be_nested_str(partition_core),
/* K10 */ be_nested_str(Partition_otadata), /* K10 */ be_nested_str(Partition_otadata),
}), }),
&be_const_str_load_otadata, &be_const_str_load_otadata,
@ -979,7 +979,7 @@ be_local_closure(Partition_parse, /* name */
/* K2 */ be_const_int(1), /* K2 */ be_const_int(1),
/* K3 */ be_nested_str(get), /* K3 */ be_nested_str(get),
/* K4 */ be_const_int(2), /* K4 */ be_const_int(2),
/* K5 */ be_nested_str(partition), /* K5 */ be_nested_str(partition_core),
/* K6 */ be_nested_str(Partition_info), /* K6 */ be_nested_str(Partition_info),
/* K7 */ be_nested_str(slots), /* K7 */ be_nested_str(slots),
/* K8 */ be_nested_str(push), /* K8 */ be_nested_str(push),
@ -1744,16 +1744,46 @@ be_local_class(Partition_info,
); );
/******************************************************************** /********************************************************************
** Solidified module: partition ** Solidified function: init
********************************************************************/ ********************************************************************/
be_local_module(partition, be_local_closure(partition_core_init, /* name */
"partition", be_nested_proto(
be_nested_map(3, 2, /* nstack */
1, /* argc */
0, /* varg */
0, /* has upvals */
NULL, /* no upvals */
0, /* has sup protos */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 2]) { /* constants */
/* K0 */ be_nested_str(global),
/* K1 */ be_nested_str(partition_core),
}),
&be_const_str_init,
&be_const_str_solidified,
( &(const binstruction[ 3]) { /* code */
0xA4060000, // 0000 IMPORT R1 K0
0x90060200, // 0001 SETMBR R1 K1 R0
0x80040000, // 0002 RET 1 R0
})
)
);
/*******************************************************************/
/********************************************************************
** Solidified module: partition_core
********************************************************************/
be_local_module(partition_core,
"partition_core",
be_nested_map(4,
( (struct bmapnode*) &(const bmapnode[]) { ( (struct bmapnode*) &(const bmapnode[]) {
{ be_const_key(Partition_info, -1), be_const_class(be_class_Partition_info) },
{ be_const_key(Partition_otadata, -1), be_const_class(be_class_Partition_otadata) }, { be_const_key(Partition_otadata, -1), be_const_class(be_class_Partition_otadata) },
{ be_const_key(Partition, 0), be_const_class(be_class_Partition) }, { be_const_key(Partition, -1), be_const_class(be_class_Partition) },
{ be_const_key(Partition_info, -1), be_const_class(be_class_Partition_info) },
{ be_const_key(init, -1), be_const_closure(partition_core_init_closure) },
})) }))
); );
BE_EXPORT_VARIABLE be_define_const_native_module(partition); BE_EXPORT_VARIABLE be_define_const_native_module(partition_core);
/********************************************************************/ /********************************************************************/

View File

@ -1,16 +1,16 @@
####################################################################### #######################################################################
# Partition manager for ESP32 - ESP32C3 - ESP32S2 # Partition manager for ESP32 - ESP32C3 - ESP32S2
# #
# use : `import partition` # use : `import partition_core`
# #
# To solidify: # To solidify:
#- #-
import solidify load("partition_embedded.be") solidify.dump(partition) import solidify load("partition_core.be") solidify.dump(partition_core)
-# -#
# Provides low-level objects and a Web UI # Provides low-level objects and a Web UI
####################################################################### #######################################################################
var partition = module('partition') var partition_core = module('partition_core')
####################################################################### #######################################################################
# Class for a partition table entry # Class for a partition table entry
@ -186,7 +186,7 @@ class Partition_info
end end
end end
partition.Partition_info = Partition_info partition_core.Partition_info = Partition_info
#------------------------------------------------------------- #-------------------------------------------------------------
- OTA Data - OTA Data
@ -343,7 +343,7 @@ class Partition_otadata
self.active_otadata, self.seq0, self.seq1, self.maxota) self.active_otadata, self.seq0, self.seq1, self.maxota)
end end
end end
partition.Partition_otadata = Partition_otadata partition_core.Partition_otadata = Partition_otadata
#------------------------------------------------------------- #-------------------------------------------------------------
- Class for a partition table entry - Class for a partition table entry
@ -373,7 +373,7 @@ class Partition
var item_raw = self.raw[i*32..(i+1)*32-1] var item_raw = self.raw[i*32..(i+1)*32-1]
var magic = item_raw.get(0,2) var magic = item_raw.get(0,2)
if magic == 0x50AA #- partition entry -# if magic == 0x50AA #- partition entry -#
var slot = partition.Partition_info(item_raw) var slot = partition_core.Partition_info(item_raw)
self.slots.push(slot) self.slots.push(slot)
elif magic == 0xEBEB #- MD5 -# elif magic == 0xEBEB #- MD5 -#
self.md5 = self.raw[i*32+16..i*33-1] self.md5 = self.raw[i*32+16..i*33-1]
@ -413,7 +413,7 @@ class Partition
end end
end end
self.otadata = partition.Partition_otadata(ota_max, otadata_offset) self.otadata = partition_core.Partition_otadata(ota_max, otadata_offset)
end end
# get the active OTA app partition number # get the active OTA app partition number
@ -485,16 +485,24 @@ class Partition
flash.write(spiffs.start + 0x1000, b) #- block #1 -# flash.write(spiffs.start + 0x1000, b) #- block #1 -#
end end
end end
partition.Partition = Partition partition_core.Partition = Partition
return partition # init method to force the global `partition_core` is defined even if the import is done within a function
def init(m)
import global
global.partition_core = m
return m
end
partition_core.init = init
return partition_core
#- Example #- Example
import partition import partition_core
# read # read
p = partition.Partition() p = partition_core.Partition()
print(p) print(p)
-# -#

View File

@ -22,154 +22,27 @@ var partition = module('partition')
# } esp_partition_info_t_simplified; # } esp_partition_info_t_simplified;
# #
####################################################################### #######################################################################
class Partition_info # class Partition_info
var type #
var subtype # def init(raw)
var start #
var size # # check if the parition is an OTA partition
var label # # if yes, return OTA number (starting at 0)
var flags # # if no, return nil
# def is_ota()
#- remove trailing NULL chars from a buffer before converting to string -# #
#- Berry strings can contain NULL, but this messes up C-Berry interface -# # # # check if the parition is a SPIFFS partition
static def remove_trailing_zeroes(b) # # returns bool
while size(b) > 0 # def is_spiffs()
if b[-1] == 0 b.resize(size(b)-1) #
else break end # # get the actual image size give of the partition
end # # returns -1 if the partition is not an app ota partition
return b # def get_image_size()
end #
# def tostring()
# #
def init(raw) # def tobytes()
if raw == nil || !issubclass(bytes, raw) # no payload, empty partition information #end
self.type = 0
self.subtype = 0
self.start = 0
self.size = 0
self.label = ''
self.flags = 0
return
end
#- we have a payload, parse it -#
var magic = raw.get(0,2)
if magic == 0x50AA #- partition entry -#
self.type = raw.get(2,1)
self.subtype = raw.get(3,1)
self.start = raw.get(4,4)
self.size = raw.get(8,4)
self.label = self.remove_trailing_zeroes(raw[12..27]).asstring()
self.flags = raw.get(28,4)
elif magic == 0xEBEB #- MD5 -#
else
import string
raise "internal_error", string.format("invalid magic number %02X", magic)
end
end
# check if the parition is an OTA partition
# if yes, return OTA number (starting at 0)
# if no, return nil
def is_ota()
if self.type == 0 && (self.subtype >= 0x10 && self.subtype < 0x20)
return self.subtype - 0x10
end
end
# check if the parition is a SPIFFS partition
# returns bool
def is_spiffs()
return self.type == 1 && self.subtype == 130
end
# get the actual image size give of the partition
# returns -1 if the partition is not an app ota partition
def get_image_size()
import flash
if self.is_ota() == nil return -1 end
try
var addr = self.start
var magic_byte = flash.read(addr, 1).get(0, 1)
if magic_byte != 0xE9 return -1 end
var seg_count = flash.read(addr+1, 1).get(0, 1)
# print("Segment count", seg_count)
var seg_offset = addr + 0x20 # sizeof(esp_image_header_t) + sizeof(esp_image_segment_header_t) = 24 + 8
for seg_num:0..seg_count-1
# print(string.format("Reading 0x%08X", seg_offset))
var segment_header = flash.read(seg_offset - 8, 8)
var seg_start_addr = segment_header.get(0, 4)
var seg_size = segment_header.get(4,4)
# print(string.format("Segment %i: flash_offset=0x%08X start_addr=0x%08X size=0x%08X", seg_num, seg_offset, seg_start_addr, seg_size))
seg_offset += seg_size + 8 # add segment_length + sizeof(esp_image_segment_header_t)
end
var total_size = seg_offset - addr + 1 # add 1KB for safety
# print(string.format("Total size = %i KB", total_size/1024))
return total_size
except .. as e, m
print("BRY: Exception> '" + e + "' - " + m)
return -1
end
end
def tostring()
import string
var type_s = ""
var subtype_s = ""
if self.type == 0 type_s = "app"
if self.subtype == 0 subtype_s = "factory"
elif self.subtype >= 0x10 && self.subtype < 0x20 subtype_s = "ota" + str(self.subtype - 0x10)
elif self.subtype == 0x20 subtype_s = "test"
end
elif self.type == 1 type_s = "data"
if self.subtype == 0x00 subtype_s = "otadata"
elif self.subtype == 0x01 subtype_s = "phy"
elif self.subtype == 0x02 subtype_s = "nvs"
elif self.subtype == 0x03 subtype_s = "coredump"
elif self.subtype == 0x04 subtype_s = "nvskeys"
elif self.subtype == 0x05 subtype_s = "efuse_em"
elif self.subtype == 0x80 subtype_s = "esphttpd"
elif self.subtype == 0x81 subtype_s = "fat"
elif self.subtype == 0x82 subtype_s = "spiffs"
end
end
#- reformat strings -#
if type_s != "" type_s = " (" + type_s + ")" end
if subtype_s != "" subtype_s = " (" + subtype_s + ")" end
return string.format("<instance: Partition_info(%d%s,%d%s,0x%08X,0x%08X,'%s',0x%X)>",
self.type, type_s,
self.subtype, subtype_s,
self.start, self.size,
self.label, self.flags)
end
def tobytes()
#- convert to raw bytes -#
var b = bytes('AA50') #- set magic number -#
b.resize(32).resize(2) #- pre-reserve 32 bytes -#
b.add(self.type, 1)
b.add(self.subtype, 1)
b.add(self.start, 4)
b.add(self.size, 4)
var label = bytes().fromstring(self.label)
label.resize(16)
b = b + label
b.add(self.flags, 4)
return b
end
end
partition.Partition_info = Partition_info
#------------------------------------------------------------- #-------------------------------------------------------------
- OTA Data - OTA Data
@ -200,302 +73,77 @@ partition.Partition_info = Partition_info
so current ota app sub type id is x , dest bin subtype is y,total ota app count is n so current ota app sub type id is x , dest bin subtype is y,total ota app count is n
seq will add (x + n*1 + 1 - seq)%n seq will add (x + n*1 + 1 - seq)%n
-------------------------------------------------------------# -------------------------------------------------------------#
class Partition_otadata # class Partition_otadata
var maxota #- number of highest OTA partition, default 1 (double ota0/ota1) -# # var maxota #- number of highest OTA partition, default 1 (double ota0/ota1) -#
var offset #- offset of the otadata partition (0x2000 in length), default 0xE000 -# # var offset #- offset of the otadata partition (0x2000 in length), default 0xE000 -#
var active_otadata #- which otadata block is active, 0 or 1, i.e. 0xE000 or 0xF000 -# # var active_otadata #- which otadata block is active, 0 or 1, i.e. 0xE000 or 0xF000 -#
var seq0 #- ota_seq of first block -# # var seq0 #- ota_seq of first block -#
var seq1 #- ota_seq of second block -# # var seq1 #- ota_seq of second block -#
#
#------------------------------------------------------------- # #- crc32 for ota_seq as 32 bits unsigned, with init vector -1 -#
- Simple CRC32 imple # static def crc32_ota_seq(seq)
- #
- adapted from Python https://rosettacode.org/wiki/CRC-32#Python # #---------------------------------------------------------------------#
-------------------------------------------------------------# # # Rest of the class
static def crc32_create_table() # #---------------------------------------------------------------------#
var a = [] # def init(maxota, offset)
for i:0..255 #
var k = i # #- update ota_max, needs to recompute everything -#
for j:0..7 # def set_ota_max(n)
if k & 1 #
k = (k >> 1) & 0x7FFFFFFF # # change the active OTA partition
k ^= 0xedb88320 # def set_active(n)
else #
k = (k >> 1) & 0x7FFFFFFF # #- load otadata from SPI Flash -#
end # def load()
end #
a.push(k) # # Save partition information to SPI Flash
end # def save()
return a #
end # # Produce a human-readable representation of the object with relevant information
static crc32_table = Partition_otadata.crc32_create_table() # def tostring()
#end
static def crc32_update(buf, crc)
crc ^= 0xffffffff
for k:0..size(buf)-1
crc = (crc >> 8 & 0x00FFFFFF) ^ Partition_otadata.crc32_table[(crc & 0xff) ^ buf[k]]
end
return crc ^ 0xffffffff
end
#- crc32 for ota_seq as 32 bits unsigned, with init vector -1 -#
static def crc32_ota_seq(seq)
return Partition_otadata.crc32_update(bytes().add(seq, 4), 0xFFFFFFFF)
end
#---------------------------------------------------------------------#
# Rest of the class
#---------------------------------------------------------------------#
def init(maxota, offset)
self.maxota = maxota
if self.maxota == nil self.maxota = 1 end
self.offset = offset
if self.offset == nil self.offset = 0xE000 end
self.active_otadata = 0
self.load()
end
#- update ota_max, needs to recompute everything -#
def set_ota_max(n)
self.maxota = n
end
# change the active OTA partition
def set_active(n)
var seq_max = 0 #- current highest seq number -#
var block_act = 0 #- block number containing the highest seq number -#
if self.seq0 != nil
seq_max = self.seq0
block_act = 0
end
if self.seq1 != nil && self.seq1 > seq_max
seq_max = self.seq1
block_act = 1
end
#- compute the next sequence number -#
var actual_ota = (seq_max - 1) % (self.maxota + 1)
if actual_ota != n #- change only if different -#
if n > actual_ota seq_max += n - actual_ota
else seq_max += (self.maxota + 1) - actual_ota + n
end
#- update internal structure -#
if block_act == 1 #- current block is 1, so update block 0 -#
self.seq0 = seq_max
else #- or write to block 1 -#
self.seq1 = seq_max
end
self._validate()
end
end
#- load otadata from SPI Flash -#
def load()
import flash
var otadata0 = flash.read(0xE000, 32)
var otadata1 = flash.read(0xF000, 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? -#
var valid1 = otadata1.get(28, 4) == self.crc32_ota_seq(self.seq1) #- is CRC32 valid? -#
if !valid0 self.seq0 = nil end
if !valid1 self.seq1 = nil end
self._validate()
end
#- internally used, validate data -#
def _validate()
self.active_otadata = 0 #- if none is valid, default to OTA0 -#
if self.seq0 != nil
self.active_otadata = (self.seq0 - 1) % (self.maxota + 1)
end
if self.seq1 != nil && (self.seq0 == nil || self.seq1 > self.seq0)
self.active_otadata = (self.seq1 - 1) % (self.maxota + 1)
end
end
# Save partition information to SPI Flash
def save()
import flash
#- check the block number to save, 0 or 1. Choose the highest ota_seq -#
var block_to_save = -1 #- invalid -#
var seq_to_save = -1 #- invalid value -#
# check seq0
if self.seq0 != nil
seq_to_save = self.seq0
block_to_save = 0
end
if (self.seq1 != nil) && (self.seq1 > seq_to_save)
seq_to_save = self.seq1
block_to_save = 1
end
# if none was good
if block_to_save < 0 block_to_save = 0 end
if seq_to_save < 0 seq_to_save = 1 end
var offset_to_save = self.offset + 0x1000 * block_to_save #- default 0xE000 or 0xF000 -#
var bytes_to_save = bytes()
bytes_to_save.add(seq_to_save, 4)
bytes_to_save += bytes("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF")
bytes_to_save.add(self.crc32_ota_seq(seq_to_save), 4)
#- erase flash area and write -#
flash.erase(offset_to_save, 0x1000)
flash.write(offset_to_save, bytes_to_save)
end
# Produce a human-readable representation of the object with relevant information
def tostring()
import string
return string.format("<instance: Partition_otadata(ota_active:%d, ota_seq=[%d,%d], ota_max=%d)>",
self.active_otadata, self.seq0, self.seq1, self.maxota)
end
end
partition.Partition_otadata = Partition_otadata
#------------------------------------------------------------- #-------------------------------------------------------------
- Class for a partition table entry - Class for a partition table entry
-------------------------------------------------------------# -------------------------------------------------------------#
class Partition #class Partition
var raw #- raw bytes of the partition table in flash -# # var raw #- raw bytes of the partition table in flash -#
var md5 #- md5 hash of partition list -# # var md5 #- md5 hash of partition list -#
var slots # var slots
var otadata #- instance of Partition_otadata() -# # var otadata #- instance of Partition_otadata() -#
#
def init() # def init()
self.slots = [] #
self.load() # # Load partition information from SPI Flash
self.parse() # def load()
self.load_otadata() #
end # def get_ota_slot(n)
#
# Load partition information from SPI Flash # #- compute the highest ota<x> partition -#
def load() # def ota_max()
import flash #
self.raw = flash.read(0x8000,0x1000) # def load_otadata()
end #
# # get the active OTA app partition number
#- parse the raw bytes to a structured list of partition items -# # def get_active()
def parse() #
for i:0..94 # there are maximum 95 slots + md5 (0xC00) # #- change the active partition -#
var item_raw = self.raw[i*32..(i+1)*32-1] # def set_active(n)
var magic = item_raw.get(0,2) #
if magic == 0x50AA #- partition entry -# # #- convert to human readble -#
var slot = Partition_info(item_raw) # def tostring()
self.slots.push(slot) #
elif magic == 0xEBEB #- MD5 -# # #- convert the slots to raw bytes, ready to falsh to parition page -#
self.md5 = self.raw[i*32+16..i*33-1] # def tobytes()
break #
else # #- write back to flash -#
break # def save()
end #
end # #- invalidate SPIFFS partition to force format at next boot -#
end # #- we simply erase the first byte of the first 2 blocks in the SPIFFS partition -#
# def invalidate_spiffs()
def get_ota_slot(n) #end
for slot: self.slots
if slot.is_ota() == n return slot end
end
return nil
end
#- compute the highest ota<x> partition -#
def ota_max()
var ota_max = 0
for slot:self.slots
if slot.type == 0 && (slot.subtype >= 0x10 && slot.subtype < 0x20)
var ota_num = slot.subtype - 0x10
if ota_num > ota_max ota_max = ota_num end
end
end
return ota_max
end
def load_otadata()
#- look for otadata partition offset, and max_ota -#
var otadata_offset = 0xE000 #- default value -#
var ota_max = self.ota_max()
for slot:self.slots
if slot.type == 1 && slot.subtype == 0 #- otadata -#
otadata_offset = slot.start
end
end
self.otadata = Partition_otadata(ota_max, otadata_offset)
end
# get the active OTA app partition number
def get_active()
return self.otadata.active_otadata
end
#- change the active partition -#
def set_active(n)
if n < 0 || n > self.ota_max() raise "value_error", "Invalid ota partition number" end
self.otadata.set_ota_max(self.ota_max()) #- update ota_max if it changed -#
self.otadata.set_active(n)
end
#- convert to human readble -#
def tostring()
var ret = "<instance: Partition([\n"
for slot: self.slots
ret += " "
ret += slot.tostring()
ret += "\n"
end
ret += "],\n "
ret += self.otadata.tostring()
ret += "\n)>"
return ret
end
#- convert the slots to raw bytes, ready to falsh to parition page -#
def tobytes()
if size(self.slots) > 95 raise "value_error", "Too many partiition slots" end
var b = bytes()
for slot: self.slots
b += slot.tobytes()
end
#- compute MD5 -#
var md5 = MD5()
md5.update(b)
#- add the last segment -#
b += bytes("EBEBFFFFFFFFFFFFFFFFFFFFFFFFFFFF")
b += md5.finish()
#- complete -#
return b
end
#- write back to flash -#
def save()
import flash
var b = self.tobytes()
#- erase flash area and write -#
flash.erase(0x8000, 0x1000)
flash.write(0x8000, b)
self.otadata.save()
end
#- invalidate SPIFFS partition to force format at next boot -#
#- we simply erase the first byte of the first 2 blocks in the SPIFFS partition -#
def invalidate_spiffs()
import flash
#- we expect the SPIFFS partition to be the last one -#
var spiffs = self.slots[-1]
if !spiffs.is_spiffs() raise 'value_error', 'No SPIFFS partition found' end
var b = bytes("00") #- flash memory: we can turn bits from '1' to '0' -#
flash.write(spiffs.start , b) #- block #0 -#
flash.write(spiffs.start + 0x1000, b) #- block #1 -#
end
end
partition.Partition = Partition
################################################################################# #################################################################################
# Partition_manager_UI # Partition_manager_UI
@ -647,8 +295,9 @@ class Partition_manager_UI
def page_part_mgr() def page_part_mgr()
import webserver import webserver
import string import string
import partition_core
if !webserver.check_privileged_access() return nil end if !webserver.check_privileged_access() return nil end
var p = partition.Partition() var p = partition_core.Partition()
webserver.content_start("Partition Manager") #- title of the web page -# webserver.content_start("Partition Manager") #- title of the web page -#
webserver.content_send_style() #- send standard Tasmota styles -# webserver.content_send_style() #- send standard Tasmota styles -#
@ -673,10 +322,11 @@ class Partition_manager_UI
def page_part_ctl() def page_part_ctl()
import webserver import webserver
import string import string
import partition_core
if !webserver.check_privileged_access() return nil end if !webserver.check_privileged_access() return nil end
#- check that the partition is valid -# #- check that the partition is valid -#
var p = partition.Partition() var p = partition_core.Partition()
try try
#---------------------------------------------------------------------# #---------------------------------------------------------------------#
@ -847,6 +497,7 @@ partition.Partition_manager_UI = Partition_manager_UI
#- create and register driver in Tasmota -# #- create and register driver in Tasmota -#
if tasmota if tasmota
import partition_core
var partition_manager_ui = partition.Partition_manager_UI() var partition_manager_ui = partition.Partition_manager_UI()
tasmota.add_driver(partition_manager_ui) tasmota.add_driver(partition_manager_ui)
## can be removed if put in 'autoexec.bat' ## can be removed if put in 'autoexec.bat'