Skip to content

Commit 07b4c09

Browse files
eboot: .RODATA, upstream uzlib, move CRC, save 112 bytes (esp8266#7844)
RODATA can be copied automatically by the bootrom, so no reason not to allow its use for strings and constants in eboot.c Revert to pfalcon's original uzlib since the single patch to remove RODATA is not required. Rationalize eboot.ld linker script, clean up BSS and init it in code. Saves 112 bytes of space in the bootloader sector by removing the extra code associated with literal loads. * Move CRC out of bootload sector We added protection to only erase the bootload sector when flashing an image when the new sector != the old sector. This was intended to minimize the chance of bricking (i.e. if there was a powerfail during flashing of the boot sector the chip would be dead). Unfortunately, by placing the CRC inside the eboot sector *every* application will have a unique eboot sector (due to the crc/len), so this protection doesn't work. Move the CRC into the first 8 bytes of IROM itself. This frees up extra space in the boot sector and ensures that eboot won't be reflashed unless there really is an eboot change.
1 parent 6c564c2 commit 07b4c09

File tree

9 files changed

+67
-108
lines changed

9 files changed

+67
-108
lines changed

.gitmodules

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,4 +24,4 @@
2424
url = https://github.com/arduino-libraries/Ethernet.git
2525
[submodule "tools/sdk/uzlib"]
2626
path = tools/sdk/uzlib
27-
url = https://github.com/earlephilhower/uzlib.git
27+
url = https://github.com/pfalcon/uzlib.git

bootloaders/eboot/Makefile

+4-4
Original file line numberDiff line numberDiff line change
@@ -40,17 +40,17 @@ APP_FW := eboot.bin
4040

4141
all: $(APP_OUT)
4242

43-
tinflate.o: $(UZLIB_PATH)/tinflate.c $(UZLIB_PATH)/uzlib.h $(UZLIB_PATH)/uzlib_conf.h
43+
tinflate.o: $(UZLIB_PATH)/tinflate.c $(UZLIB_PATH)/uzlib.h $(UZLIB_PATH)/uzlib_conf.h Makefile
4444
$(CC) $(CFLAGS) -c -o tinflate.o $(UZLIB_PATH)/tinflate.c
4545

46-
tinfgzip.o: $(UZLIB_PATH)/tinfgzip.c $(UZLIB_PATH)/uzlib.h $(UZLIB_PATH)/uzlib_conf.h
46+
tinfgzip.o: $(UZLIB_PATH)/tinfgzip.c $(UZLIB_PATH)/uzlib.h $(UZLIB_PATH)/uzlib_conf.h Makefile
4747
$(CC) $(CFLAGS) -c -o tinfgzip.o $(UZLIB_PATH)/tinfgzip.c
4848

49-
$(APP_AR): $(TARGET_OBJ_PATHS) tinflate.o tinfgzip.o
49+
$(APP_AR): $(TARGET_OBJ_PATHS) tinflate.o tinfgzip.o Makefile
5050
$(AR) cru $@ $^
5151

5252
$(APP_OUT): $(APP_AR) eboot.ld | Makefile
53-
$(LD) $(LD_SCRIPT) $(LDFLAGS) -Wl,--start-group -Wl,--whole-archive $(APP_AR) -Wl,--end-group -o $@
53+
$(LD) $(LD_SCRIPT) $(LDFLAGS) -Wl,--start-group -Wl,--sort-common $(APP_AR) -Wl,--end-group -o $@
5454

5555
clean:
5656
rm -f *.o

bootloaders/eboot/eboot.c

+17-25
Original file line numberDiff line numberDiff line change
@@ -14,28 +14,19 @@
1414
#include "eboot_command.h"
1515
#include <uzlib.h>
1616

17-
extern unsigned char _gzip_dict;
1817

1918
#define SWRST do { (*((volatile uint32_t*) 0x60000700)) |= 0x80000000; } while(0);
2019

2120
extern void ets_wdt_enable(void);
2221
extern void ets_wdt_disable(void);
2322

24-
// Converts bit of a string into a uint32
25-
#define S(a,b,c,d) ( (((uint32_t)a) & 0xff) | (((uint32_t)b) << 8) | (((uint32_t)c) << 16) | (((uint32_t)d)<<24) )
26-
2723
int print_version(const uint32_t flash_addr)
2824
{
2925
uint32_t ver;
3026
if (SPIRead(flash_addr + APP_START_OFFSET + sizeof(image_header_t) + sizeof(section_header_t), &ver, sizeof(ver))) {
3127
return 1;
3228
}
33-
// We don't have BSS and can't print from flash, so build up string
34-
// 4 chars at a time. Smaller code than byte-wise assignment.
35-
uint32_t fmt[2];
36-
fmt[0] = S('v', '%', '0', '8');
37-
fmt[1] = S('x', '\n', 0, 0);
38-
ets_printf((const char*) fmt, ver);
29+
ets_printf("v%08x\n", ver);
3930
return 0;
4031
}
4132

@@ -222,6 +213,16 @@ int main()
222213
bool clear_cmd = false;
223214
struct eboot_command cmd;
224215

216+
// BSS init commented out for now to save space. If any static variables set
217+
// to 0 are used, need to uncomment it or else the BSS will not be cleared and
218+
// the static vars will power on with random values.
219+
#if 0
220+
// Clear BSS ourselves, we don't have handy C runtime
221+
extern char _bss_start;
222+
extern char _bss_end;
223+
ets_bzero(&_bss_start, &_bss_end - &_bss_start);
224+
#endif
225+
225226
print_version(0);
226227

227228
if (eboot_command_read(&cmd) == 0) {
@@ -236,32 +237,26 @@ int main()
236237
}
237238

238239
if (cmd.action == ACTION_COPY_RAW) {
239-
uint32_t cp = S('c', 'p', ':', 0);
240-
ets_printf((const char *)&cp);
240+
ets_printf("cp:");
241241

242242
ets_wdt_disable();
243243
res = copy_raw(cmd.args[0], cmd.args[1], cmd.args[2], false);
244244
ets_wdt_enable();
245245

246-
cp = S('0' + res, '\n', 0, 0 );
247-
ets_printf((const char *)&cp);
246+
ets_printf("%d\n", res);
248247
#if 0
249248
//devyte: this verify step below (cmp:) only works when the end of copy operation above does not overwrite the
250249
//beginning of the image in the empty area, see #7458. Disabling for now.
251250
//TODO: replace the below verify with hash type, crc, or similar.
252251
// Verify the copy
253-
uint32_t v[2];
254-
v[0] = S('c', 'm', 'p', ':');
255-
v[1] = 0;
256-
ets_printf(const char *)v);
252+
ets_printf("cmp:");
257253
if (res == 0) {
258254
ets_wdt_disable();
259255
res = copy_raw(cmd.args[0], cmd.args[1], cmd.args[2], true);
260256
ets_wdt_enable();
261257
}
262258

263-
cp = S('0' + res, '\n', 0, 0 );
264-
ets_printf((const char *)&cp);
259+
ets_printf("%d\n", res);
265260
#endif
266261
if (res == 0) {
267262
cmd.action = ACTION_LOAD_APP;
@@ -274,13 +269,10 @@ int main()
274269
}
275270

276271
if (cmd.action == ACTION_LOAD_APP) {
277-
ets_putc('l'); ets_putc('d'); ets_putc('\n');
272+
ets_printf("ld\n");
278273
res = load_app_from_flash_raw(cmd.args[0]);
279274
// We will get to this only on load fail
280-
uint32_t e[2];
281-
e[0] = S('e', ':', '0' + res, '\n' );
282-
e[1] = 0;
283-
ets_printf((const char*)e);
275+
ets_printf("e:%d\n", res);
284276
}
285277

286278
if (res) {

bootloaders/eboot/eboot.elf

43.1 KB
Binary file not shown.

bootloaders/eboot/eboot.ld

+24-66
Original file line numberDiff line numberDiff line change
@@ -42,53 +42,13 @@ PROVIDE(_memmap_cacheattr_reset = _memmap_cacheattr_wb_trapnull);
4242
SECTIONS
4343
{
4444

45-
.dport0.rodata : ALIGN(4)
46-
{
47-
_dport0_rodata_start = ABSOLUTE(.);
48-
*(.dport0.rodata)
49-
*(.dport.rodata)
50-
_dport0_rodata_end = ABSOLUTE(.);
51-
} >dport0_0_seg :dport0_0_phdr
52-
53-
.dport0.literal : ALIGN(4)
54-
{
55-
_dport0_literal_start = ABSOLUTE(.);
56-
*(.dport0.literal)
57-
*(.dport.literal)
58-
_dport0_literal_end = ABSOLUTE(.);
59-
} >dport0_0_seg :dport0_0_phdr
60-
61-
.dport0.data : ALIGN(4)
62-
{
63-
_dport0_data_start = ABSOLUTE(.);
64-
*(.dport0.data)
65-
*(.dport.data)
66-
_dport0_data_end = ABSOLUTE(.);
67-
} >dport0_0_seg :dport0_0_phdr
68-
69-
.data : ALIGN(4)
45+
.globals : ALIGN(4)
7046
{
7147
*(COMMON) /* Global vars */
72-
. = ALIGN(4);
73-
_heap_start = ABSOLUTE(.);
74-
/* _stack_sentry = ALIGN(0x8); */
7548
} >dram0_0_seg :dram0_0_bss_phdr
76-
/* __stack = 0x3ffc8000; */
7749

78-
.text : ALIGN(4)
50+
.data : ALIGN(4)
7951
{
80-
_stext = .;
81-
_text_start = ABSOLUTE(.);
82-
*(.entry.text)
83-
*(.init.literal)
84-
*(.init)
85-
*(.literal .text .literal.* .text.* .stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*)
86-
*(.fini.literal)
87-
*(.fini)
88-
*(.gnu.version)
89-
_text_end = ABSOLUTE(.);
90-
_etext = .;
91-
. = ALIGN (8);
9252
_data_start = ABSOLUTE(.);
9353
*(.data)
9454
*(.data.*)
@@ -102,7 +62,10 @@ SECTIONS
10262
*(.gnu.linkonce.s2.*)
10363
*(.jcr)
10464
_data_end = ABSOLUTE(.);
105-
. = ALIGN (8);
65+
} >dram0_0_seg :dram0_0_bss_phdr
66+
67+
.rodata : ALIGN(4)
68+
{
10669
_rodata_start = ABSOLUTE(.);
10770
*(.rodata)
10871
*(.rodata.*)
@@ -131,14 +94,11 @@ SECTIONS
13194
*(.xt_except_desc_end)
13295
*(.dynamic)
13396
*(.gnu.version_d)
134-
. = ALIGN(4); /* this table MUST be 4-byte aligned */
135-
_bss_table_start = ABSOLUTE(.);
136-
LONG(_bss_start)
137-
LONG(_bss_end)
138-
_bss_table_end = ABSOLUTE(.);
13997
_rodata_end = ABSOLUTE(.);
98+
} >dram0_0_seg :dram0_0_bss_phdr
14099

141-
. = ALIGN (8);
100+
.bss : ALIGN(4)
101+
{
142102
_bss_start = ABSOLUTE(.);
143103
*(.dynsbss)
144104
*(.sbss)
@@ -152,26 +112,24 @@ SECTIONS
152112
*(.bss)
153113
*(.bss.*)
154114
*(.gnu.linkonce.b.*)
155-
. = ALIGN (8);
156115
_bss_end = ABSOLUTE(.);
157-
_free_space = 4096 - 17 - (. - _stext);
158-
/*
159-
The boot loader checksum must be before the CRC, which is written by elf2bin.py.
160-
This leaves 16 bytes after the checksum for the CRC placed at the end of the
161-
4096-byte sector. */
162-
_cs_here = (ALIGN((. + 1), 16) == ALIGN(16)) ? (ALIGN(16) - 1) : (. + 0x0F);
116+
} >dram0_0_seg :dram0_0_bss_phdr
163117

164-
/*
165-
The filling (padding) and values for _crc_size and _crc_val are handled by
166-
elf2bin.py. With this, we give values to the symbols without explicitly
167-
assigning space. This avoids the linkers back *fill* operation that causes
168-
trouble.
169118

170-
The CRC info is stored in last 8 bytes. */
171-
_crc_size = _stext + 4096 - 8;
172-
_crc_val = _stext + 4096 - 4;
173-
ASSERT((4096 > (17 + (. - _stext))), "Error: No space for CS and CRC in bootloader sector.");
174-
ASSERT((_crc_size > _cs_here), "Error: CRC must be located after CS.");
119+
.text : ALIGN(4)
120+
{
121+
_stext = .;
122+
_text_start = ABSOLUTE(.);
123+
*(.entry.text)
124+
*(.init.literal)
125+
*(.init)
126+
*(.literal .text .literal.* .text.* .stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*)
127+
*(.fini.literal)
128+
*(.fini)
129+
*(.gnu.version)
130+
_text_end = ABSOLUTE(.);
131+
_etext = .;
132+
. = ALIGN (4); /* Ensure 32b alignment since this is written to IRAM */
175133
} >iram1_0_seg :iram1_0_phdr
176134

177135
.lit4 : ALIGN(4)

cores/esp8266/Esp.cpp

+10-8
Original file line numberDiff line numberDiff line change
@@ -444,22 +444,24 @@ bool EspClass::checkFlashConfig(bool needsEquals) {
444444
return false;
445445
}
446446

447+
// These are defined in the linker script, and filled in by the elf2bin.py util
448+
extern "C" uint32_t __crc_len;
449+
extern "C" uint32_t __crc_val;
450+
447451
bool EspClass::checkFlashCRC() {
448-
// The CRC and total length are placed in extra space at the end of the 4K chunk
449-
// of flash occupied by the bootloader. If the bootloader grows to >4K-8 bytes,
450-
// we'll need to adjust this.
451-
uint32_t flashsize = *((uint32_t*)(0x40200000 + 4088)); // Start of PROGMEM plus 4K-8
452-
uint32_t flashcrc = *((uint32_t*)(0x40200000 + 4092)); // Start of PROGMEM plus 4K-4
452+
// Dummy CRC fill
453453
uint32_t z[2];
454454
z[0] = z[1] = 0;
455455

456+
uint32_t firstPart = (uintptr_t)&__crc_len - 0x40200000; // How many bytes to check before the 1st CRC val
457+
456458
// Start the checksum
457-
uint32_t crc = crc32((const void*)0x40200000, 4096-8, 0xffffffff);
459+
uint32_t crc = crc32((const void*)0x40200000, firstPart, 0xffffffff);
458460
// Pretend the 2 words of crc/len are zero to be idempotent
459461
crc = crc32(z, 8, crc);
460462
// Finish the CRC calculation over the rest of flash
461-
crc = crc32((const void*)0x40201000, flashsize-4096, crc);
462-
return crc == flashcrc;
463+
crc = crc32((const void*)(0x40200000 + firstPart + 8), __crc_len - (firstPart + 8), crc);
464+
return crc == __crc_val;
463465
}
464466

465467

tools/elf2bin.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@
3030
ffreqb = { '40': 0, '26': 1, '20': 2, '80': 15 }
3131
fsizeb = { '512K': 0, '256K': 1, '1M': 2, '2M': 3, '4M': 4, '8M': 8, '16M': 9 }
3232

33-
crcsize_offset = 4088
34-
crcval_offset = 4092
33+
crcsize_offset = 4096 + 16
34+
crcval_offset = 4096 + 16 + 4
3535

3636
def get_elf_entry(elf, path):
3737
p = subprocess.Popen([path + "/xtensa-lx106-elf-readelf", '-h', elf], stdout=subprocess.PIPE, universal_newlines=True )
@@ -188,7 +188,7 @@ def wrapper(**kwargs):
188188

189189
wrapper(
190190
elf=args.eboot,
191-
segments=[".text"],
191+
segments=[".text", ".rodata"],
192192
to_addr=4096
193193
)
194194

tools/sdk/ld/eagle.app.v6.common.ld.h

+7
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,13 @@ SECTIONS
147147
.irom0.text : ALIGN(4)
148148
{
149149
_irom0_text_start = ABSOLUTE(.);
150+
151+
/* Stuff the CRC in well known symbols at a well known location */
152+
__crc_len = ABSOLUTE(.);
153+
LONG(0x00000000);
154+
__crc_val = ABSOLUTE(.);
155+
LONG(0x00000000);
156+
150157
*(.ver_number)
151158
*.c.o(.literal*, .text*)
152159
*.cpp.o(EXCLUDE_FILE (umm_malloc.cpp.o) .literal*, EXCLUDE_FILE (umm_malloc.cpp.o) .text*)

tools/sdk/uzlib

0 commit comments

Comments
 (0)