├── LICENSE
├── Makefile
├── README.md
├── build
├── .gitignore
├── boards
│ ├── B-L072Z-LRWAN1
│ │ └── Makefile
│ ├── NUCLEO-L053R8
│ │ └── Makefile
│ ├── NUCLEO-L073RZ
│ │ └── Makefile
│ ├── main.mk
│ └── simul-unicorn
│ │ └── Makefile
└── makefiles
│ ├── arm.mk
│ ├── stm32lx.mk
│ ├── toolchain.mk
│ └── unicorn.mk
├── doc
├── img
│ ├── fw-done.svg
│ ├── fw-init.svg
│ ├── fw-lz4-1.svg
│ ├── fw-lz4-2.svg
│ ├── fw-lz4-3.svg
│ ├── fw-lz4-dict-1.svg
│ ├── fw-lz4-dict-2.svg
│ ├── fw-lz4-dict-3.svg
│ ├── fw-lz4-dict-4.svg
│ ├── fw-lz4-dict-5.svg
│ ├── fw-lz4-dict-inplace-1.svg
│ ├── fw-lz4-dict-inplace-2.svg
│ ├── fw-lz4-dict-inplace-3.svg
│ ├── fw-plain-1.svg
│ ├── fw-plain-2.svg
│ ├── fw-plain-3.svg
│ └── illustrations.odg
└── uptypes.md
├── example
├── .gitignore
└── stm32l0
│ ├── .gitignore
│ ├── Makefile
│ ├── fw.ld
│ └── hello.c
├── src
├── arm
│ ├── CMSIS
│ │ ├── Device
│ │ │ └── ST
│ │ │ │ ├── STM32L0xx
│ │ │ │ └── Include
│ │ │ │ │ ├── stm32l051xx.h
│ │ │ │ │ ├── stm32l052xx.h
│ │ │ │ │ ├── stm32l053xx.h
│ │ │ │ │ ├── stm32l061xx.h
│ │ │ │ │ ├── stm32l062xx.h
│ │ │ │ │ ├── stm32l063xx.h
│ │ │ │ │ ├── stm32l071xx.h
│ │ │ │ │ ├── stm32l072xx.h
│ │ │ │ │ ├── stm32l073xx.h
│ │ │ │ │ ├── stm32l081xx.h
│ │ │ │ │ ├── stm32l082xx.h
│ │ │ │ │ ├── stm32l083xx.h
│ │ │ │ │ ├── stm32l0xx.h
│ │ │ │ │ └── system_stm32l0xx.h
│ │ │ │ └── STM32L1xx
│ │ │ │ └── Include
│ │ │ │ ├── stm32l1xx.h
│ │ │ │ └── system_stm32l1xx.h
│ │ └── Include
│ │ │ ├── arm_common_tables.h
│ │ │ ├── arm_const_structs.h
│ │ │ ├── arm_math.h
│ │ │ ├── core_cm0.h
│ │ │ ├── core_cm0plus.h
│ │ │ ├── core_cm3.h
│ │ │ ├── core_cm4.h
│ │ │ ├── core_cm7.h
│ │ │ ├── core_cmFunc.h
│ │ │ ├── core_cmInstr.h
│ │ │ ├── core_cmSimd.h
│ │ │ ├── core_sc000.h
│ │ │ └── core_sc300.h
│ ├── stm32lx
│ │ ├── bootloader.c
│ │ ├── bootloader_hw.h
│ │ ├── bootloader_impl.h
│ │ ├── boottab.h
│ │ ├── ld
│ │ │ ├── STM32L0.ld
│ │ │ ├── STM32L0xx8.ld
│ │ │ ├── STM32L0xxB.ld
│ │ │ └── STM32L0xxZ.ld
│ │ ├── startup.S
│ │ └── util.S
│ └── unicorn
│ │ ├── bootloader.c
│ │ ├── bootloader_impl.h
│ │ ├── boottab.h
│ │ └── ld
│ │ ├── bootloader.ld
│ │ └── mem.ld
└── common
│ ├── .gitignore
│ ├── Makefile
│ ├── bootloader.h
│ ├── lz4.c
│ ├── lz4.h
│ ├── sha2.c
│ ├── sha2.h
│ ├── update.c
│ └── update.h
└── tools
├── fwtool
├── .gitignore
├── signtool.py
└── zfwtool.py
└── shavs
├── shabytetestvectors.zip
└── shavs.py
/LICENSE:
--------------------------------------------------------------------------------
1 | --- Revised 3-Clause BSD License ---
2 | Copyright (C) 2016-2019, SEMTECH (International) AG.
3 | All rights reserved.
4 |
5 | Redistribution and use in source and binary forms, with or without modification,
6 | are permitted provided that the following conditions are met:
7 |
8 | * Redistributions of source code must retain the above copyright notice,
9 | this list of conditions and the following disclaimer.
10 | * Redistributions in binary form must reproduce the above copyright notice,
11 | this list of conditions and the following disclaimer in the documentation
12 | and/or other materials provided with the distribution.
13 | * Neither the name of the copyright holder nor the names of its contributors
14 | may be used to endorse or promote products derived from this software
15 | without specific prior written permission.
16 |
17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
18 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 | DISCLAIMED. IN NO EVENT SHALL SEMTECH BE LIABLE FOR ANY DIRECT, INDIRECT,
21 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
23 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
24 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25 | OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
26 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | BOARDDIRS=$(dir $(wildcard build/boards/*/Makefile))
2 |
3 | default:
4 |
5 | %:
6 | for BOARDDIR in $(BOARDDIRS); do $(MAKE) -C $${BOARDDIR} $@; done
7 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Basic Loader
2 |
3 | Basic Loader is an update-capable bootloader that supports the unpacking and
4 | installing of new firmware on an end-device.
5 |
6 | Basic MAC uses this component to load its firmware, and to support firmware
7 | updates over-the-air (FUOTA).
8 |
9 | ## Building Basic Loader
10 |
11 | The reference hardware platform for Basic Loader is the B-L072Z-LRWAN1 STM32
12 | LoRa™ Discovery kit.
13 |
14 | ### Prerequisites
15 | It is recommended to use a recent Ubuntu distribution as build host with the
16 | `gcc-arm-embedded` package installed.
17 |
18 | To build the bootloaders for all supported platforms, simply run `make` in
19 | the toplevel directory.
20 |
21 | Alternatively, change into a specific target board's build directory and run
22 | `make` there:
23 |
24 | ```
25 | cd build/boards/B-L072Z-LRWAN1
26 | make
27 | ```
28 |
29 | The output of the build process is a file named `bootloader.hex` that can be
30 | loaded onto the B-L072Z-LRWAN1 development board. If there is no valid firmware
31 | installed, the LED LD2 will be flashing the corresponding error sequence
32 | (SYNC-2-2-1).
33 |
34 | ## Release Notes
35 |
36 | ### Release 4
37 | 16-Jan-2020
38 |
39 | - Support for LZ4 in-place delta updates
40 | - Bugfix: Flash writing routines
41 | - Improved readability of LED blink sequence
42 | - Option to blink LED during update process
43 | - Improved out-of-tree build support
44 | - Improved ZFW (firmware patching) tool
45 |
46 | ### Release 3
47 | 01-May-2019
48 |
49 | - Bootloader for STM32 makes SHA-256 function available to firmware
50 | - New ZFW-tool creates firmware archives with metadata
51 | - Changed linker scripts to work around a recent [regression in GNU
52 | ld](https://sourceware.org/bugzilla/show_bug.cgi?id=24289)
53 | - Bugfixes
54 |
55 | ### Pre-release 2
56 | 15-Jan-2019
57 |
58 | - Bootloader for STM32 makes Flash-write function available to firmware
59 |
60 | ### Pre-release 1
61 | 07-Jan-2019
62 |
63 | - Verifies and loads firmware
64 | - Tool for patching firmware image header
65 | - Support for plain updates
66 |
--------------------------------------------------------------------------------
/build/.gitignore:
--------------------------------------------------------------------------------
1 | Makefile.local
2 | bootloader
3 | *.o
4 | *.d
5 | *.hex
6 | *.map
7 |
--------------------------------------------------------------------------------
/build/boards/B-L072Z-LRWAN1/Makefile:
--------------------------------------------------------------------------------
1 | FLAVOR := stm32lx
2 | MCU := STM32L072Z
3 |
4 | include ../main.mk
5 |
6 | CDEFS += BOOT_LED_GPIO="GPIO('A',5,0)"
7 | CDEFS += UPDATE_LED_GPIO="GPIO('A',5,0)"
8 |
--------------------------------------------------------------------------------
/build/boards/NUCLEO-L053R8/Makefile:
--------------------------------------------------------------------------------
1 | FLAVOR := stm32lx
2 | MCU := STM32L053R8
3 |
4 | include ../main.mk
5 |
6 | CDEFS += BOOT_LED_GPIO="GPIO('A',5,0)"
7 |
--------------------------------------------------------------------------------
/build/boards/NUCLEO-L073RZ/Makefile:
--------------------------------------------------------------------------------
1 | FLAVOR := stm32lx
2 | MCU := STM32L073Z
3 |
4 | include ../main.mk
5 |
6 | CDEFS += BOOT_LED_GPIO="GPIO('A',5,0)"
7 |
--------------------------------------------------------------------------------
/build/boards/main.mk:
--------------------------------------------------------------------------------
1 | TOPDIR ?= ../../..
2 | MKDIR := $(TOPDIR)/build/makefiles
3 | SRCDIR := $(TOPDIR)/src
4 |
5 | -include Makefile.local
6 | -include $(MKDIR)/Makefile.local
7 |
8 | FLAVOR ?= $(error FLAVOR not set)
9 |
10 | default:
11 |
12 | include $(MKDIR)/$(FLAVOR).mk
13 |
--------------------------------------------------------------------------------
/build/boards/simul-unicorn/Makefile:
--------------------------------------------------------------------------------
1 | FLAVOR := unicorn
2 |
3 | include ../main.mk
4 |
--------------------------------------------------------------------------------
/build/makefiles/arm.mk:
--------------------------------------------------------------------------------
1 | TOOLCHAIN := gcc
2 | CROSS_COMPILE += arm-none-eabi-
3 |
4 | include $(MKDIR)/toolchain.mk
5 |
6 | CMSIS := $(SRCDIR)/arm/CMSIS
7 |
8 | CFLAGS += -fno-common -fno-builtin -fno-exceptions -ffunction-sections -fdata-sections -fomit-frame-pointer
9 | CFLAGS += -I$(CMSIS)/Include
10 |
11 | LDFLAGS += -nostartfiles
12 |
--------------------------------------------------------------------------------
/build/makefiles/stm32lx.mk:
--------------------------------------------------------------------------------
1 | include $(MKDIR)/arm.mk
2 |
3 | VPATH += $(SRCDIR)/arm/stm32lx
4 | VPATH += $(SRCDIR)/common
5 | VPATH += $(SRCDIR)/common/micro-ecc
6 |
7 | SRCS += bootloader.c
8 | SRCS += util.S
9 | SRCS += startup.S
10 |
11 | SRCS += update.c
12 | SRCS += sha2.c
13 | SRCS += lz4.c
14 |
15 |
16 | STM32 := $(shell echo $(MCU) | sed 's/^STM32\(L[01]\)\([0-9][0-9]\)R\?\([8BZ]\)$$/ok t\/\1 v\/\2 s\/\3/')
17 | ifneq (ok,$(firstword $(STM32)))
18 | $(error Could not parse MCU: $(MCU))
19 | endif
20 | STM32_T := $(notdir $(filter t/%,$(STM32)))
21 | STM32_V := $(notdir $(filter v/%,$(STM32)))
22 | STM32_S := $(notdir $(filter s/%,$(STM32)))
23 |
24 |
25 | DEFS += STM32$(STM32_T)
26 | DEFS += STM32$(STM32_T)$(STM32_V)xx
27 |
28 | DEFS += LZ4_PAGEBUFFER_SZ=128
29 | DEFS += UP_PAGEBUFFER_SZ=128
30 |
31 | FLAGS += -mcpu=cortex-m0plus
32 | FLAGS += -I$(SRCDIR)/common
33 |
34 | CFLAGS += -Wall
35 | CFLAGS += -Os
36 | CFLAGS += -I$(SRCDIR)/arm/CMSIS/Device/ST/STM32$(STM32_T)xx/Include
37 |
38 | LDFLAGS += -mcpu=cortex-m0plus
39 | LDFLAGS += -T$(SRCDIR)/arm/stm32lx/ld/STM32$(STM32_T)xx$(STM32_S).ld
40 | LDFLAGS += -T$(SRCDIR)/arm/stm32lx/ld/STM32$(STM32_T).ld
41 |
42 | OBJS = $(addsuffix .o,$(basename $(SRCS)))
43 |
44 | bootloader: $(OBJS)
45 |
46 | bootloader.hex: bootloader
47 | $(HEX) $< $@
48 |
49 | default: bootloader.hex
50 |
51 |
52 | clean:
53 | rm -f *.o *.d *.map bootloader bootloader.hex bootloader.bin
54 |
55 | .PHONY: clean default
56 |
57 |
58 | MAKE_DEPS := $(MAKEFILE_LIST) # before we include all the *.d files
59 |
60 | -include $(OBJS:.o=.d)
61 |
62 | $(OBJS): $(MAKE_DEPS)
63 |
--------------------------------------------------------------------------------
/build/makefiles/toolchain.mk:
--------------------------------------------------------------------------------
1 | ifeq ($(TOOLCHAIN),gcc)
2 | FLAGS += -MMD -MP
3 | FLAGS += -g
4 | CFLAGS += -std=gnu11
5 | LDFLAGS += -Wl,--gc-sections -Wl,-Map,$(basename $@).map
6 | CC := $(CROSS_COMPILE)gcc
7 | AS := $(CROSS_COMPILE)as
8 | LD := $(CROSS_COMPILE)gcc
9 | HEX := $(CROSS_COMPILE)objcopy -O ihex
10 | BIN := $(CROSS_COMPILE)objcopy -O binary
11 | endif
12 |
13 | CDEFS += $(DEFS)
14 | ASDEFS += $(DEFS) ASSEMBLY
15 | CFLAGS += $(addprefix -D,$(CDEFS))
16 | ASFLAGS += $(addprefix -D,$(ASDEFS))
17 |
18 | CFLAGS += $(FLAGS)
19 | ASFLAGS += $(FLAGS)
20 |
--------------------------------------------------------------------------------
/build/makefiles/unicorn.mk:
--------------------------------------------------------------------------------
1 | include $(MKDIR)/arm.mk
2 |
3 | VPATH += $(SRCDIR)/arm/unicorn
4 | VPATH += $(SRCDIR)/common
5 | VPATH += $(SRCDIR)/common/micro-ecc
6 |
7 | SRCS += bootloader.c
8 |
9 | SRCS += update.c
10 | SRCS += sha2.c
11 | SRCS += lz4.c
12 |
13 | DEFS += UP_PAGEBUFFER_SZ=128
14 |
15 | FLAGS += -mcpu=cortex-m0plus
16 | FLAGS += -I$(SRCDIR)/common
17 |
18 | CFLAGS += -Wall
19 | CFLAGS += -Os
20 |
21 | LDFLAGS += -mcpu=cortex-m0plus
22 | LDFLAGS += -T$(SRCDIR)/arm/unicorn/ld/mem.ld
23 | LDFLAGS += -T$(SRCDIR)/arm/unicorn/ld/bootloader.ld
24 |
25 | OBJS = $(addsuffix .o,$(basename $(SRCS)))
26 |
27 | bootloader: $(OBJS)
28 |
29 | bootloader.hex: bootloader
30 | $(HEX) $< $@
31 |
32 | default: bootloader.hex
33 |
34 |
35 | clean:
36 | rm -f *.o *.d *.map bootloader bootloader.hex bootloader.bin
37 |
38 | .PHONY: clean default
39 |
40 |
41 | MAKE_DEPS := $(MAKEFILE_LIST) # before we include all the *.d files
42 |
43 | -include $(OBJS:.o=.d)
44 |
45 | $(OBJS): $(MAKE_DEPS)
46 |
--------------------------------------------------------------------------------
/doc/img/fw-done.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 | BL
92 |
93 |
94 |
95 | BL
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 | New firmware
120 |
121 |
122 |
123 | New firmware
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
--------------------------------------------------------------------------------
/doc/img/fw-init.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 | BL
95 |
96 |
97 |
98 | BL
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 | Current firmware
123 |
124 |
125 |
126 | Current firmware
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
--------------------------------------------------------------------------------
/doc/img/fw-lz4-1.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 | BL
103 |
104 |
105 |
106 | BL
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 | Current firmware
131 |
132 |
133 |
134 | Current firmware
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 | Update (lz4)
185 |
186 |
187 |
188 | Update (lz4)
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
--------------------------------------------------------------------------------
/doc/img/fw-lz4-3.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 | BL
101 |
102 |
103 |
104 | BL
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 | New firmware
129 |
130 |
131 |
132 | New firmware
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 | Update (lz4)
183 |
184 |
185 |
186 | Update (lz4)
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
--------------------------------------------------------------------------------
/doc/img/fw-lz4-dict-1.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 | BL
105 |
106 |
107 |
108 | BL
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 | Current firmware
133 |
134 |
135 |
136 | Current firmware
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 | Update (lz4-dict)
187 |
188 |
189 |
190 | Update (lz4-dict)
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
--------------------------------------------------------------------------------
/doc/img/fw-plain-1.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 | BL
101 |
102 |
103 |
104 | BL
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 | Current firmware
129 |
130 |
131 |
132 | Current firmware
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 | Update (plain)
183 |
184 |
185 |
186 | Update (plain)
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
--------------------------------------------------------------------------------
/doc/img/fw-plain-3.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 | BL
100 |
101 |
102 |
103 | BL
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 | New firmware
128 |
129 |
130 |
131 | New firmware
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 | Update (plain)
182 |
183 |
184 |
185 | Update (plain)
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
--------------------------------------------------------------------------------
/doc/img/illustrations.odg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lorabasics/basicloader/a1e6086dd9b106d9a563427bea9da14f614edb7e/doc/img/illustrations.odg
--------------------------------------------------------------------------------
/doc/uptypes.md:
--------------------------------------------------------------------------------
1 | # Firmware Update Types
2 |
3 | ## Update Process
4 |
5 | Initially, only the bootloader and the original firmware reside in
6 | the device Flash memory. Generally, the bootloader is located at the
7 | very beginning, followed by the current firmware. The bootloader
8 | component is static and does not change, nor is it updatable itself.
9 |
10 |
11 |
12 | It is the application's responsility to place an available update
13 | somewhere in Flash memory, preferrably at the very end to maximize
14 | the available space for updating. Updating overwrites the current
15 | firmware, leaving only the new firmware in Flash memory.
16 |
17 |
18 |
19 | As the update process is destructive, extreme care is taken to make
20 | this step robust. It is implemented in such a way that in case of
21 | interruption, the update can be restarted or resumed. This ensures
22 | that even in the case of power-loss or other transient failure, the
23 | bootloader can continue updating on the next pass, leaving the device
24 | with a functioning firmware.
25 |
26 | The bootloader supports a number of different update types:
27 |
28 | - Plain Updates
29 | - LZ4 Compressed Updates
30 | - LZ4 Delta Updates
31 | - LZ4 In-Place Delta Updates
32 |
33 | ### Plain Updates (`plain`)
34 |
35 | Plain updates are the most simple way to perform an update. The full
36 | new firmware image is contained as-is in the update blob.
37 |
38 |
39 |
40 | The bootloader then simply copies the firmware from the update blob
41 | to its intended location.
42 |
43 |
44 |
45 | After the process is complete, the new firmware is in place and the
46 | update can be invalidated.
47 |
48 |
49 |
50 | ### LZ4 Compressed Updates (`lz4`)
51 |
52 | LZ4 compressed updates differ from plain updates only by using [LZ4
53 | compression](https://en.wikipedia.org/wiki/LZ4_(compression_algorithm))
54 | to reduce the size of the update. LZ4 was chosen because of the
55 | simplicity and robustness of the decompressor.
56 |
57 |
58 |
59 | The bootloader then decompresses the firmware from the update blob
60 | to its intended location.
61 |
62 |
63 |
64 | After the process is complete, the new firmware is in place and the
65 | update can be invalidated.
66 |
67 |
68 |
69 | ### LZ4 Delta Updates (`lz4-dict`)
70 |
71 | :wastebasket: *Deprecated*
72 |
73 | LZ4 delta updates make use of _dictionary mode_, whereby data can be
74 | preloaded into the backreferences space. For delta updates, the
75 | previous firmware image is used as the dictionary. This can dramatically
76 | reduce the size of an update, but since decompression requires access
77 | to the dictionary, the update is now specific to the source firmware
78 | it was created for. Further, the entire dictionary must stay available
79 | during the decompression process, which means the original firmware
80 | cannot be decompressed directly to the intended location.
81 |
82 |
83 |
84 | LZ4 delta updates are therefore encoded as plain udpates before the
85 | compression step. The bootloader then decompresses this plain update
86 | blob into free Flash memory between the compressed update and the
87 | current firmware, while using the current firmware as dictionary.
88 |
89 |
90 |
91 | Once the decompression is complete, the plain update is available
92 | in Flash and the compressed update can be invalidated.
93 |
94 |
95 |
96 | The process then continues by using the plain update as above.
97 |
98 |
99 |
100 | After the process is complete, the new firmware is in place and the
101 | update can be invalidated.
102 |
103 |
104 |
105 | As can be seen, while LZ4 delta updates are quite small and can thus
106 | be transmitted very efficiently over-the-air, the two-step decompression
107 | method uses much more Flash memory than any of the other methods.
108 |
109 | ### LZ4 In-Place Delta Updates (`lz4-dict-inplace`)
110 |
111 | By carefully coding the update and making use of a temporary scratch
112 | buffer, the delta update can be extracted directly to its final location
113 | in Flash memory. This dramatically reduces the amount of free space
114 | necessary on the device. The scratch buffer's size can be variable,
115 | thereby allowing the trading of compression efficiency against Flash
116 | memory requirements.
117 |
118 |
119 |
120 | The new firmware is uncompressed one block at a time into a temporary
121 | scratch buffer, before it is copied to its final location. The update
122 | blob contains itegrity protection data for each block to allow transactional
123 | execution of this update method.
124 |
125 |
126 |
127 | While not the entire previous firmware is available as a dictionary
128 | for every block with this method, it still yields compression efficiency
129 | comparable to regular delta updates in practice.
130 |
131 | After the process is complete, the new firmware is in place and the
132 | update can be invalidated.
133 |
134 |
135 |
--------------------------------------------------------------------------------
/example/.gitignore:
--------------------------------------------------------------------------------
1 | *.o
2 | *.d
3 | *.hex
4 | *.map
5 | *.zfw
6 |
--------------------------------------------------------------------------------
/example/stm32l0/.gitignore:
--------------------------------------------------------------------------------
1 | hello
2 |
--------------------------------------------------------------------------------
/example/stm32l0/Makefile:
--------------------------------------------------------------------------------
1 | CC := arm-none-eabi-gcc
2 |
3 | CFLAGS += -std=gnu11
4 | CFLAGS += -Wall
5 | CFLAGS += -g
6 |
7 | CFLAGS += -mcpu=cortex-m0plus -fno-common -fno-builtin -fno-exceptions -ffunction-sections -fdata-sections -fomit-frame-pointer
8 |
9 | CFLAGS += -I../../src/common
10 | CFLAGS += -I../../src/arm/stm32lx
11 | CFLAGS += -I../../src/arm/CMSIS/Include
12 | CFLAGS += -I../../src/arm/CMSIS/Device/ST/STM32L0xx/Include
13 |
14 | LDFLAGS += -Wl,--gc-sections -Wl,-Map,$(basename $@).map
15 | LDFLAGS += -nostdlib
16 | LDFLAGS += -T../../src/arm/stm32lx/ld/STM32L0xxB.ld
17 | LDFLAGS += -Tfw.ld
18 |
19 | ZFWTOOL := ../../tools/fwtool/zfwtool.py
20 |
21 | hello.hex: hello.zfw
22 | $(ZFWTOOL) export $< $@
23 |
24 | hello.zfw: hello.unpatched.hex
25 | $(ZFWTOOL) create --patch $< $@
26 |
27 | hello.unpatched.hex: hello
28 | arm-none-eabi-objcopy -O ihex $< $@
29 |
30 | hello: hello.o
31 |
32 | clean:
33 | rm -f *.o *.map hello hello.hex
34 |
35 | .PHONY: clean
36 |
37 | .DELETE_ON_ERROR:
38 |
--------------------------------------------------------------------------------
/example/stm32l0/fw.ld:
--------------------------------------------------------------------------------
1 | SECTIONS {
2 | .text : {
3 | . = ALIGN(4);
4 | KEEP(*(.fwhdr))
5 | . = ALIGN(4);
6 | *(.text)
7 | *(.text*)
8 | . = ALIGN(4);
9 | } >FWFLASH
10 |
11 | .data : {
12 | . = ALIGN(4);
13 | _sdata = .;
14 | KEEP(*(.isr))
15 | *(.data)
16 | *(.data*)
17 | . = ALIGN(4);
18 | _edata = .;
19 | } >RAM AT>FWFLASH
20 |
21 | _sidata = LOADADDR(.data);
22 |
23 | .bss : {
24 | . = ALIGN(4);
25 | _sbss = .;
26 | *(.bss)
27 | *(.bss*)
28 | *(COMMON)
29 | . = ALIGN(4);
30 | _ebss = .;
31 | } >RAM
32 |
33 | .rodata : {
34 | . = ALIGN(4);
35 | *(.rodata)
36 | *(.rodata*)
37 | . = ALIGN(4);
38 |
39 | /* make sure flash image is a multiple of page size */
40 | FILL(0xffffffff)
41 | . = ALIGN(128);
42 | __fw_end__ = .;
43 | } >FWFLASH
44 | }
45 |
--------------------------------------------------------------------------------
/example/stm32l0/hello.c:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2016-2019 Semtech (International) AG. All rights reserved.
2 | //
3 | // This file is subject to the terms and conditions defined in file 'LICENSE',
4 | // which is part of this source code package.
5 |
6 | #include "stm32l072xx.h"
7 | #include "bootloader.h"
8 | #include "boottab.h"
9 |
10 | void _start (boot_boottab* boottab); // forward declaration
11 |
12 | // Firmware header
13 | __attribute__((section(".fwhdr")))
14 | const volatile boot_fwhdr fwhdr = {
15 | // CRC and size will be patched by external tool
16 | .crc = 0,
17 | .size = BOOT_MAGIC_SIZE,
18 | .entrypoint = (uint32_t) _start,
19 | };
20 |
21 | static void clock_init (void) {
22 | // System is clocked by MSI @2.1MHz at startup
23 | // We want to go to PLL(HSI16) @32MHz
24 |
25 | // 1a. HSI: Enable
26 | RCC->CR |= RCC_CR_HSION;
27 | // 1b. HSI: Wait for it
28 | while ((RCC->CR & RCC_CR_HSIRDY) == 0);
29 |
30 | // 2a. Flash: Enable prefetch buffer
31 | FLASH->ACR |= FLASH_ACR_PRFTEN;
32 | // 2b. Flash: Use 1 Wait state
33 | FLASH->ACR |= FLASH_ACR_LATENCY;
34 | while ((FLASH->ACR & FLASH_ACR_LATENCY) == 0);
35 |
36 | // 3a. Power: Enable clock
37 | RCC->APB1ENR |= RCC_APB1ENR_PWREN;
38 | // 3b. Power: Select Vrange 1 (min. 1.71V!)
39 | PWR->CR = PWR_CR_VOS_0;
40 | // 3c. Power: Wait for regulator
41 | while ((PWR->CSR & PWR_CSR_VOSF) != 0);
42 |
43 | // 4a. PLL: Set source (HSI16), multiplier (4), divider (2)
44 | RCC->CFGR |= (RCC_CFGR_PLLSRC_HSI | RCC_CFGR_PLLMUL4 | RCC_CFGR_PLLDIV2);
45 | // 4b. PLL: Enable
46 | RCC->CR |= RCC_CR_PLLON;
47 | // 4c. PLL: Wait for it
48 | while ((RCC->CR & RCC_CR_PLLRDY) == 0);
49 |
50 | // 5a. System clock: Set source (PLL)
51 | RCC->CFGR |= RCC_CFGR_SW_PLL;
52 | // 5b. System clock: Wait for it
53 | while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL);
54 |
55 | // 6. Turn off MSI
56 | RCC->CR &= ~RCC_CR_MSION;
57 | }
58 |
59 | static void uart_init (void) {
60 | // Configure USART (115200/8N1, TX)
61 | RCC->APB1ENR |= RCC_APB1ENR_USART2EN;
62 | USART2->BRR = 278; // 115200 (APB1 clock @32MHz)
63 | USART2->CR1 = USART_CR1_UE | USART_CR1_TE;
64 |
65 | // Configure GPIO (PA2 / USART2_TX / AF4)
66 | RCC->IOPENR |= RCC_IOPENR_GPIOAEN;
67 | GPIOA->AFR[0] = (GPIOA->AFR[0] & ~(7 << (4 * (2)))) | (4 << (4 * (2))); /* af 4 */
68 | GPIOA->MODER = (GPIOA->MODER & ~(3 << (2 * (2)))) | (2 << (2 * (2))); /* alternate func */
69 | GPIOA->PUPDR = (GPIOA->PUPDR & ~(3 << (2 * (2)))) | (0 << (2 * (2))); /* no pull-up/down */
70 | GPIOA->OTYPER = (GPIOA->OTYPER & ~(1 << (1 * (2)))) | (0 << (1 * (2))); /* push-pull */
71 | GPIOA->OSPEEDR = (GPIOA->OSPEEDR & ~(3 << (2 * (2)))) | (1 << (2 * (2))); /* medium speed */
72 | }
73 |
74 | static void uart_print (char* s) {
75 | while (*s) {
76 | while ((USART2->ISR & USART_ISR_TXE) == 0);
77 | USART2->TDR = *s++;
78 | }
79 | }
80 |
81 | static void i2h (char* dst, uint32_t v) {
82 | dst[8] = '\0';
83 | for (int i = 0; i < 8; i++) {
84 | dst[7 - i] = "0123456789abcdef"[v & 0xf];
85 | v >>= 4;
86 | }
87 | }
88 |
89 | void _start (boot_boottab* boottab) {
90 | // We only use stack in this example. A real firmware
91 | // would need to do initialization at this point, e.g.
92 | // data / bss segments, ISR vector re-map, etc.
93 |
94 | char crcbuf[8+1];
95 |
96 | clock_init();
97 | uart_init();
98 |
99 | uart_print("----------------------\r\n");
100 | uart_print("Hello World!\r\n");
101 |
102 | uart_print("Build: " __DATE__ " " __TIME__ "\r\n");
103 |
104 | i2h(crcbuf, boottab->version);
105 | uart_print("Bootloader: 0x");
106 | uart_print(crcbuf);
107 | uart_print("\r\n");
108 |
109 | i2h(crcbuf, fwhdr.crc);
110 | uart_print("Firmware: 0x");
111 | uart_print(crcbuf);
112 | uart_print("\r\n");
113 |
114 | while (1) __WFI(); // good night
115 | }
116 |
--------------------------------------------------------------------------------
/src/arm/CMSIS/Device/ST/STM32L0xx/Include/stm32l0xx.h:
--------------------------------------------------------------------------------
1 | /**
2 | ******************************************************************************
3 | * @file stm32l0xx.h
4 | * @author MCD Application Team
5 | * @version V1.2.0
6 | * @date 06-February-2015
7 | * @brief CMSIS Cortex-M0+ Device Peripheral Access Layer Header File.
8 | * This file contains all the peripheral register's definitions, bits
9 | * definitions and memory mapping for STM32L0xx devices.
10 | *
11 | * The file is the unique include file that the application programmer
12 | * is using in the C source code, usually in main.c. This file contains:
13 | * - Configuration section that allows to select:
14 | * - The device used in the target application
15 | * - To use or not the peripheral’s drivers in application code(i.e.
16 | * code will be based on direct access to peripheral’s registers
17 | * rather than drivers API), this option is controlled by
18 | * "#define USE_HAL_DRIVER"
19 | *
20 | ******************************************************************************
21 | * @attention
22 | *
23 | *
© COPYRIGHT(c) 2015 STMicroelectronics
24 | *
25 | * Redistribution and use in source and binary forms, with or without modification,
26 | * are permitted provided that the following conditions are met:
27 | * 1. Redistributions of source code must retain the above copyright notice,
28 | * this list of conditions and the following disclaimer.
29 | * 2. Redistributions in binary form must reproduce the above copyright notice,
30 | * this list of conditions and the following disclaimer in the documentation
31 | * and/or other materials provided with the distribution.
32 | * 3. Neither the name of STMicroelectronics nor the names of its contributors
33 | * may be used to endorse or promote products derived from this software
34 | * without specific prior written permission.
35 | *
36 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
37 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
38 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
40 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
41 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
42 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
43 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
44 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
45 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
46 | *
47 | ******************************************************************************
48 | */
49 |
50 | /** @addtogroup CMSIS
51 | * @{
52 | */
53 |
54 | /** @addtogroup stm32l0xx
55 | * @{
56 | */
57 |
58 | #ifndef __STM32L0xx_H
59 | #define __STM32L0xx_H
60 |
61 | #ifdef __cplusplus
62 | extern "C" {
63 | #endif /* __cplusplus */
64 |
65 | /** @addtogroup Library_configuration_section
66 | * @{
67 | */
68 |
69 | /**
70 | * @brief STM32 Family
71 | */
72 | #if !defined (STM32L0)
73 | #define STM32L0
74 | #endif /* STM32L0 */
75 |
76 | /* Uncomment the line below according to the target STM32 device used in your
77 | application
78 | */
79 |
80 | #if !defined (STM32L051xx) && !defined (STM32L052xx) && !defined (STM32L053xx) && !defined (STM32L061xx) && !defined (STM32L062xx) && !defined (STM32L063xx) \
81 | && !defined (STM32L071xx) && !defined (STM32L072xx) && !defined (STM32L073xx) && !defined (STM32L081xx) && !defined (STM32L082xx) && !defined (STM32L083xx)
82 | /* #define STM32L051xx */ /*!< STM32L051K8, STM32L051C6, STM32L051C8, STM32L051R6, STM32L051R8 Devices */
83 | /* #define STM32L052xx */ /*!< STM32L052K6, STM32L052K8, STM32L052C6, STM32L052C8, STM32L052R6, STM32L052R8 Devices */
84 | /* #define STM32L053xx */ /*!< STM32L053C6, STM32L053C8, STM32L053R6, STM32L053R8 Devices */
85 | /* #define STM32L061xx */ /*!< */
86 | /* #define STM32L062xx */ /*!< STM32L062K8 */
87 | /* #define STM32L063xx */ /*!< STM32L063C8, STM32L063R8 */
88 | /* #define STM32L071xx */ /*!< */
89 | /* #define STM32L072xx */ /*!< */
90 | /* #define STM32L073xx */ /*!< STM32L073V8, STM32L073VB, STM32L073RB, STM32L073VZ, STM32L073RZ Devices */
91 | /* #define STM32L081xx */ /*!< */
92 | /* #define STM32L082xx */ /*!< */
93 | /* #define STM32L083xx */ /*!< */
94 | #endif
95 |
96 | /* Tip: To avoid modifying this file each time you need to switch between these
97 | devices, you can define the device in your toolchain compiler preprocessor.
98 | */
99 | #if !defined (USE_HAL_DRIVER)
100 | /**
101 | * @brief Comment the line below if you will not use the peripherals drivers.
102 | In this case, these drivers will not be included and the application code will
103 | be based on direct access to peripherals registers
104 | */
105 | /*#define USE_HAL_DRIVER */
106 | #endif /* USE_HAL_DRIVER */
107 |
108 | /**
109 | * @brief CMSIS Device version number V1.2.0RC1
110 | */
111 | #define __STM32L0xx_CMSIS_DEVICE_VERSION_MAIN (0x01) /*!< [31:24] main version */
112 | #define __STM32L0xx_CMSIS_DEVICE_VERSION_SUB1 (0x02) /*!< [23:16] sub1 version */
113 | #define __STM32L0xx_CMSIS_DEVICE_VERSION_SUB2 (0x00) /*!< [15:8] sub2 version */
114 | #define __STM32L0xx_CMSIS_DEVICE_VERSION_RC (0x00) /*!< [7:0] release candidate */
115 | #define __STM32L0xx_CMSIS_DEVICE_VERSION ((__CMSIS_DEVICE_VERSION_MAIN << 24)\
116 | |(__CMSIS_DEVICE_HAL_VERSION_SUB1 << 16)\
117 | |(__CMSIS_DEVICE_HAL_VERSION_SUB2 << 8 )\
118 | |(__CMSIS_DEVICE_HAL_VERSION_RC))
119 |
120 | /**
121 | * @}
122 | */
123 |
124 | /** @addtogroup Device_Included
125 | * @{
126 | */
127 |
128 | #if defined(STM32L031xx)
129 | #include "stm32l031xx.h"
130 | #elif defined(STM32L041xx)
131 | #include "stm32l041xx.h"
132 | #elif defined(STM32L051xx)
133 | #include "stm32l051xx.h"
134 | #elif defined(STM32L052xx)
135 | #include "stm32l052xx.h"
136 | #elif defined(STM32L053xx)
137 | #include "stm32l053xx.h"
138 | #elif defined(STM32L062xx)
139 | #include "stm32l062xx.h"
140 | #elif defined(STM32L063xx)
141 | #include "stm32l063xx.h"
142 | #elif defined(STM32L061xx)
143 | #include "stm32l061xx.h"
144 | #elif defined(STM32L071xx)
145 | #include "stm32l071xx.h"
146 | #elif defined(STM32L072xx)
147 | #include "stm32l072xx.h"
148 | #elif defined(STM32L073xx)
149 | #include "stm32l073xx.h"
150 | #elif defined(STM32L082xx)
151 | #include "stm32l082xx.h"
152 | #elif defined(STM32L083xx)
153 | #include "stm32l083xx.h"
154 | #elif defined(STM32L081xx)
155 | #include "stm32l081xx.h"
156 | #else
157 | #error "Please select first the target STM32L0xx device used in your application (in stm32l0xx.h file)"
158 | #endif
159 |
160 | /**
161 | * @}
162 | */
163 |
164 | /** @addtogroup Exported_types
165 | * @{
166 | */
167 | typedef enum
168 | {
169 | RESET = 0,
170 | SET = !RESET
171 | } FlagStatus, ITStatus;
172 |
173 | typedef enum
174 | {
175 | DISABLE = 0,
176 | ENABLE = !DISABLE
177 | } FunctionalState;
178 | #define IS_FUNCTIONAL_STATE(STATE) (((STATE) == DISABLE) || ((STATE) == ENABLE))
179 |
180 | typedef enum
181 | {
182 | ERROR = 0,
183 | SUCCESS = !ERROR
184 | } ErrorStatus;
185 |
186 | /**
187 | * @}
188 | */
189 |
190 |
191 | /** @addtogroup Exported_macro
192 | * @{
193 | */
194 | #define SET_BIT(REG, BIT) ((REG) |= (BIT))
195 |
196 | #define CLEAR_BIT(REG, BIT) ((REG) &= ~(BIT))
197 |
198 | #define READ_BIT(REG, BIT) ((REG) & (BIT))
199 |
200 | #define CLEAR_REG(REG) ((REG) = (0x0))
201 |
202 | #define WRITE_REG(REG, VAL) ((REG) = (VAL))
203 |
204 | #define READ_REG(REG) ((REG))
205 |
206 | #define MODIFY_REG(REG, CLEARMASK, SETMASK) WRITE_REG((REG), (((READ_REG(REG)) & (~(CLEARMASK))) | (SETMASK)))
207 |
208 |
209 | /**
210 | * @}
211 | */
212 |
213 | #if defined (USE_HAL_DRIVER)
214 | #include "stm32l0xx_hal.h"
215 | #endif /* USE_HAL_DRIVER */
216 |
217 | #ifdef __cplusplus
218 | }
219 | #endif /* __cplusplus */
220 |
221 | #endif /* __STM32L0xx_H */
222 | /**
223 | * @}
224 | */
225 |
226 | /**
227 | * @}
228 | */
229 |
230 |
231 |
232 |
233 | /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
234 |
--------------------------------------------------------------------------------
/src/arm/CMSIS/Device/ST/STM32L0xx/Include/system_stm32l0xx.h:
--------------------------------------------------------------------------------
1 | /**
2 | ******************************************************************************
3 | * @file system_stm32l0xx.h
4 | * @author MCD Application Team
5 | * @version V1.2.0
6 | * @date 06-February-2015
7 | * @brief CMSIS Cortex-M0+ Device Peripheral Access Layer System Header File.
8 | ******************************************************************************
9 | * @attention
10 | *
11 | * © COPYRIGHT(c) 2015 STMicroelectronics
12 | *
13 | * Redistribution and use in source and binary forms, with or without modification,
14 | * are permitted provided that the following conditions are met:
15 | * 1. Redistributions of source code must retain the above copyright notice,
16 | * this list of conditions and the following disclaimer.
17 | * 2. Redistributions in binary form must reproduce the above copyright notice,
18 | * this list of conditions and the following disclaimer in the documentation
19 | * and/or other materials provided with the distribution.
20 | * 3. Neither the name of STMicroelectronics nor the names of its contributors
21 | * may be used to endorse or promote products derived from this software
22 | * without specific prior written permission.
23 | *
24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
28 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
30 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
31 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
32 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
33 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 | *
35 | ******************************************************************************
36 | */
37 |
38 | /** @addtogroup CMSIS
39 | * @{
40 | */
41 |
42 | /** @addtogroup stm32l0xx_system
43 | * @{
44 | */
45 |
46 | /**
47 | * @brief Define to prevent recursive inclusion
48 | */
49 | #ifndef __SYSTEM_STM32L0XX_H
50 | #define __SYSTEM_STM32L0XX_H
51 |
52 | #ifdef __cplusplus
53 | extern "C" {
54 | #endif
55 |
56 | /** @addtogroup STM32L0xx_System_Includes
57 | * @{
58 | */
59 |
60 | /**
61 | * @}
62 | */
63 |
64 |
65 | /** @addtogroup STM32L0xx_System_Exported_types
66 | * @{
67 | */
68 | /* This variable is updated in three ways:
69 | 1) by calling CMSIS function SystemCoreClockUpdate()
70 | 2) by calling HAL API function HAL_RCC_GetSysClockFreq()
71 | 3) each time HAL_RCC_ClockConfig() is called to configure the system clock frequency
72 | Note: If you use this function to configure the system clock; then there
73 | is no need to call the 2 first functions listed above, since SystemCoreClock
74 | variable is updated automatically.
75 | */
76 | extern uint32_t SystemCoreClock; /*!< System Clock Frequency (Core Clock) */
77 |
78 | /**
79 | * @}
80 | */
81 |
82 | /** @addtogroup STM32L0xx_System_Exported_Constants
83 | * @{
84 | */
85 |
86 | /**
87 | * @}
88 | */
89 |
90 | /** @addtogroup STM32L0xx_System_Exported_Macros
91 | * @{
92 | */
93 |
94 | /**
95 | * @}
96 | */
97 |
98 | /** @addtogroup STM32L0xx_System_Exported_Functions
99 | * @{
100 | */
101 |
102 | extern void SystemInit(void);
103 | extern void SystemCoreClockUpdate(void);
104 | /**
105 | * @}
106 | */
107 |
108 | #ifdef __cplusplus
109 | }
110 | #endif
111 |
112 | #endif /*__SYSTEM_STM32L0XX_H */
113 |
114 | /**
115 | * @}
116 | */
117 |
118 | /**
119 | * @}
120 | */
121 | /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
122 |
--------------------------------------------------------------------------------
/src/arm/CMSIS/Device/ST/STM32L1xx/Include/stm32l1xx.h:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lorabasics/basicloader/a1e6086dd9b106d9a563427bea9da14f614edb7e/src/arm/CMSIS/Device/ST/STM32L1xx/Include/stm32l1xx.h
--------------------------------------------------------------------------------
/src/arm/CMSIS/Device/ST/STM32L1xx/Include/system_stm32l1xx.h:
--------------------------------------------------------------------------------
1 | /**
2 | ******************************************************************************
3 | * @file system_stm32l1xx.h
4 | * @author MCD Application Team
5 | * @version V1.3.3
6 | * @date 20-April-2015
7 | * @brief CMSIS Cortex-M3 Device Peripheral Access Layer System Header File.
8 | ******************************************************************************
9 | * @attention
10 | *
11 | * © COPYRIGHT 2015 STMicroelectronics
12 | *
13 | * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
14 | * You may not use this file except in compliance with the License.
15 | * You may obtain a copy of the License at:
16 | *
17 | * http://www.st.com/software_license_agreement_liberty_v2
18 | *
19 | * Unless required by applicable law or agreed to in writing, software
20 | * distributed under the License is distributed on an "AS IS" BASIS,
21 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22 | * See the License for the specific language governing permissions and
23 | * limitations under the License.
24 | *
25 | ******************************************************************************
26 | */
27 |
28 | /** @addtogroup CMSIS
29 | * @{
30 | */
31 |
32 | /** @addtogroup stm32l1xx_system
33 | * @{
34 | */
35 |
36 | /**
37 | * @brief Define to prevent recursive inclusion
38 | */
39 | #ifndef __SYSTEM_STM32L1XX_H
40 | #define __SYSTEM_STM32L1XX_H
41 |
42 | #ifdef __cplusplus
43 | extern "C" {
44 | #endif
45 |
46 | /** @addtogroup STM32L1xx_System_Includes
47 | * @{
48 | */
49 |
50 | /**
51 | * @}
52 | */
53 |
54 |
55 | /** @addtogroup STM32L1xx_System_Exported_types
56 | * @{
57 | */
58 |
59 | extern uint32_t SystemCoreClock; /*!< System Clock Frequency (Core Clock) */
60 |
61 | /**
62 | * @}
63 | */
64 |
65 | /** @addtogroup STM32L1xx_System_Exported_Constants
66 | * @{
67 | */
68 |
69 | /**
70 | * @}
71 | */
72 |
73 | /** @addtogroup STM32L1xx_System_Exported_Macros
74 | * @{
75 | */
76 |
77 | /**
78 | * @}
79 | */
80 |
81 | /** @addtogroup STM32L1xx_System_Exported_Functions
82 | * @{
83 | */
84 |
85 | extern void SystemInit(void);
86 | extern void SystemCoreClockUpdate(void);
87 | /**
88 | * @}
89 | */
90 |
91 | #ifdef __cplusplus
92 | }
93 | #endif
94 |
95 | #endif /*__SYSTEM_STM32L1XX_H */
96 |
97 | /**
98 | * @}
99 | */
100 |
101 | /**
102 | * @}
103 | */
104 | /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
105 |
--------------------------------------------------------------------------------
/src/arm/CMSIS/Include/arm_common_tables.h:
--------------------------------------------------------------------------------
1 | /* ----------------------------------------------------------------------
2 | * Copyright (C) 2010-2014 ARM Limited. All rights reserved.
3 | *
4 | * $Date: 31. July 2014
5 | * $Revision: V1.4.4
6 | *
7 | * Project: CMSIS DSP Library
8 | * Title: arm_common_tables.h
9 | *
10 | * Description: This file has extern declaration for common tables like Bitreverse, reciprocal etc which are used across different functions
11 | *
12 | * Target Processor: Cortex-M4/Cortex-M3
13 | *
14 | * Redistribution and use in source and binary forms, with or without
15 | * modification, are permitted provided that the following conditions
16 | * are met:
17 | * - Redistributions of source code must retain the above copyright
18 | * notice, this list of conditions and the following disclaimer.
19 | * - Redistributions in binary form must reproduce the above copyright
20 | * notice, this list of conditions and the following disclaimer in
21 | * the documentation and/or other materials provided with the
22 | * distribution.
23 | * - Neither the name of ARM LIMITED nor the names of its contributors
24 | * may be used to endorse or promote products derived from this
25 | * software without specific prior written permission.
26 | *
27 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
28 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
29 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
30 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
31 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
32 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
33 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
34 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
35 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
36 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
37 | * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38 | * POSSIBILITY OF SUCH DAMAGE.
39 | * -------------------------------------------------------------------- */
40 |
41 | #ifndef _ARM_COMMON_TABLES_H
42 | #define _ARM_COMMON_TABLES_H
43 |
44 | #include "arm_math.h"
45 |
46 | extern const uint16_t armBitRevTable[1024];
47 | extern const q15_t armRecipTableQ15[64];
48 | extern const q31_t armRecipTableQ31[64];
49 | //extern const q31_t realCoefAQ31[1024];
50 | //extern const q31_t realCoefBQ31[1024];
51 | extern const float32_t twiddleCoef_16[32];
52 | extern const float32_t twiddleCoef_32[64];
53 | extern const float32_t twiddleCoef_64[128];
54 | extern const float32_t twiddleCoef_128[256];
55 | extern const float32_t twiddleCoef_256[512];
56 | extern const float32_t twiddleCoef_512[1024];
57 | extern const float32_t twiddleCoef_1024[2048];
58 | extern const float32_t twiddleCoef_2048[4096];
59 | extern const float32_t twiddleCoef_4096[8192];
60 | #define twiddleCoef twiddleCoef_4096
61 | extern const q31_t twiddleCoef_16_q31[24];
62 | extern const q31_t twiddleCoef_32_q31[48];
63 | extern const q31_t twiddleCoef_64_q31[96];
64 | extern const q31_t twiddleCoef_128_q31[192];
65 | extern const q31_t twiddleCoef_256_q31[384];
66 | extern const q31_t twiddleCoef_512_q31[768];
67 | extern const q31_t twiddleCoef_1024_q31[1536];
68 | extern const q31_t twiddleCoef_2048_q31[3072];
69 | extern const q31_t twiddleCoef_4096_q31[6144];
70 | extern const q15_t twiddleCoef_16_q15[24];
71 | extern const q15_t twiddleCoef_32_q15[48];
72 | extern const q15_t twiddleCoef_64_q15[96];
73 | extern const q15_t twiddleCoef_128_q15[192];
74 | extern const q15_t twiddleCoef_256_q15[384];
75 | extern const q15_t twiddleCoef_512_q15[768];
76 | extern const q15_t twiddleCoef_1024_q15[1536];
77 | extern const q15_t twiddleCoef_2048_q15[3072];
78 | extern const q15_t twiddleCoef_4096_q15[6144];
79 | extern const float32_t twiddleCoef_rfft_32[32];
80 | extern const float32_t twiddleCoef_rfft_64[64];
81 | extern const float32_t twiddleCoef_rfft_128[128];
82 | extern const float32_t twiddleCoef_rfft_256[256];
83 | extern const float32_t twiddleCoef_rfft_512[512];
84 | extern const float32_t twiddleCoef_rfft_1024[1024];
85 | extern const float32_t twiddleCoef_rfft_2048[2048];
86 | extern const float32_t twiddleCoef_rfft_4096[4096];
87 |
88 |
89 | /* floating-point bit reversal tables */
90 | #define ARMBITREVINDEXTABLE__16_TABLE_LENGTH ((uint16_t)20 )
91 | #define ARMBITREVINDEXTABLE__32_TABLE_LENGTH ((uint16_t)48 )
92 | #define ARMBITREVINDEXTABLE__64_TABLE_LENGTH ((uint16_t)56 )
93 | #define ARMBITREVINDEXTABLE_128_TABLE_LENGTH ((uint16_t)208 )
94 | #define ARMBITREVINDEXTABLE_256_TABLE_LENGTH ((uint16_t)440 )
95 | #define ARMBITREVINDEXTABLE_512_TABLE_LENGTH ((uint16_t)448 )
96 | #define ARMBITREVINDEXTABLE1024_TABLE_LENGTH ((uint16_t)1800)
97 | #define ARMBITREVINDEXTABLE2048_TABLE_LENGTH ((uint16_t)3808)
98 | #define ARMBITREVINDEXTABLE4096_TABLE_LENGTH ((uint16_t)4032)
99 |
100 | extern const uint16_t armBitRevIndexTable16[ARMBITREVINDEXTABLE__16_TABLE_LENGTH];
101 | extern const uint16_t armBitRevIndexTable32[ARMBITREVINDEXTABLE__32_TABLE_LENGTH];
102 | extern const uint16_t armBitRevIndexTable64[ARMBITREVINDEXTABLE__64_TABLE_LENGTH];
103 | extern const uint16_t armBitRevIndexTable128[ARMBITREVINDEXTABLE_128_TABLE_LENGTH];
104 | extern const uint16_t armBitRevIndexTable256[ARMBITREVINDEXTABLE_256_TABLE_LENGTH];
105 | extern const uint16_t armBitRevIndexTable512[ARMBITREVINDEXTABLE_512_TABLE_LENGTH];
106 | extern const uint16_t armBitRevIndexTable1024[ARMBITREVINDEXTABLE1024_TABLE_LENGTH];
107 | extern const uint16_t armBitRevIndexTable2048[ARMBITREVINDEXTABLE2048_TABLE_LENGTH];
108 | extern const uint16_t armBitRevIndexTable4096[ARMBITREVINDEXTABLE4096_TABLE_LENGTH];
109 |
110 | /* fixed-point bit reversal tables */
111 | #define ARMBITREVINDEXTABLE_FIXED___16_TABLE_LENGTH ((uint16_t)12 )
112 | #define ARMBITREVINDEXTABLE_FIXED___32_TABLE_LENGTH ((uint16_t)24 )
113 | #define ARMBITREVINDEXTABLE_FIXED___64_TABLE_LENGTH ((uint16_t)56 )
114 | #define ARMBITREVINDEXTABLE_FIXED__128_TABLE_LENGTH ((uint16_t)112 )
115 | #define ARMBITREVINDEXTABLE_FIXED__256_TABLE_LENGTH ((uint16_t)240 )
116 | #define ARMBITREVINDEXTABLE_FIXED__512_TABLE_LENGTH ((uint16_t)480 )
117 | #define ARMBITREVINDEXTABLE_FIXED_1024_TABLE_LENGTH ((uint16_t)992 )
118 | #define ARMBITREVINDEXTABLE_FIXED_2048_TABLE_LENGTH ((uint16_t)1984)
119 | #define ARMBITREVINDEXTABLE_FIXED_4096_TABLE_LENGTH ((uint16_t)4032)
120 |
121 | extern const uint16_t armBitRevIndexTable_fixed_16[ARMBITREVINDEXTABLE_FIXED___16_TABLE_LENGTH];
122 | extern const uint16_t armBitRevIndexTable_fixed_32[ARMBITREVINDEXTABLE_FIXED___32_TABLE_LENGTH];
123 | extern const uint16_t armBitRevIndexTable_fixed_64[ARMBITREVINDEXTABLE_FIXED___64_TABLE_LENGTH];
124 | extern const uint16_t armBitRevIndexTable_fixed_128[ARMBITREVINDEXTABLE_FIXED__128_TABLE_LENGTH];
125 | extern const uint16_t armBitRevIndexTable_fixed_256[ARMBITREVINDEXTABLE_FIXED__256_TABLE_LENGTH];
126 | extern const uint16_t armBitRevIndexTable_fixed_512[ARMBITREVINDEXTABLE_FIXED__512_TABLE_LENGTH];
127 | extern const uint16_t armBitRevIndexTable_fixed_1024[ARMBITREVINDEXTABLE_FIXED_1024_TABLE_LENGTH];
128 | extern const uint16_t armBitRevIndexTable_fixed_2048[ARMBITREVINDEXTABLE_FIXED_2048_TABLE_LENGTH];
129 | extern const uint16_t armBitRevIndexTable_fixed_4096[ARMBITREVINDEXTABLE_FIXED_4096_TABLE_LENGTH];
130 |
131 | /* Tables for Fast Math Sine and Cosine */
132 | extern const float32_t sinTable_f32[FAST_MATH_TABLE_SIZE + 1];
133 | extern const q31_t sinTable_q31[FAST_MATH_TABLE_SIZE + 1];
134 | extern const q15_t sinTable_q15[FAST_MATH_TABLE_SIZE + 1];
135 |
136 | #endif /* ARM_COMMON_TABLES_H */
137 |
--------------------------------------------------------------------------------
/src/arm/CMSIS/Include/arm_const_structs.h:
--------------------------------------------------------------------------------
1 | /* ----------------------------------------------------------------------
2 | * Copyright (C) 2010-2014 ARM Limited. All rights reserved.
3 | *
4 | * $Date: 31. July 2014
5 | * $Revision: V1.4.4
6 | *
7 | * Project: CMSIS DSP Library
8 | * Title: arm_const_structs.h
9 | *
10 | * Description: This file has constant structs that are initialized for
11 | * user convenience. For example, some can be given as
12 | * arguments to the arm_cfft_f32() function.
13 | *
14 | * Target Processor: Cortex-M4/Cortex-M3
15 | *
16 | * Redistribution and use in source and binary forms, with or without
17 | * modification, are permitted provided that the following conditions
18 | * are met:
19 | * - Redistributions of source code must retain the above copyright
20 | * notice, this list of conditions and the following disclaimer.
21 | * - Redistributions in binary form must reproduce the above copyright
22 | * notice, this list of conditions and the following disclaimer in
23 | * the documentation and/or other materials provided with the
24 | * distribution.
25 | * - Neither the name of ARM LIMITED nor the names of its contributors
26 | * may be used to endorse or promote products derived from this
27 | * software without specific prior written permission.
28 | *
29 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
30 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
31 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
32 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
33 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
34 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
35 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
36 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
37 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
38 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
39 | * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
40 | * POSSIBILITY OF SUCH DAMAGE.
41 | * -------------------------------------------------------------------- */
42 |
43 | #ifndef _ARM_CONST_STRUCTS_H
44 | #define _ARM_CONST_STRUCTS_H
45 |
46 | #include "arm_math.h"
47 | #include "arm_common_tables.h"
48 |
49 | extern const arm_cfft_instance_f32 arm_cfft_sR_f32_len16;
50 | extern const arm_cfft_instance_f32 arm_cfft_sR_f32_len32;
51 | extern const arm_cfft_instance_f32 arm_cfft_sR_f32_len64;
52 | extern const arm_cfft_instance_f32 arm_cfft_sR_f32_len128;
53 | extern const arm_cfft_instance_f32 arm_cfft_sR_f32_len256;
54 | extern const arm_cfft_instance_f32 arm_cfft_sR_f32_len512;
55 | extern const arm_cfft_instance_f32 arm_cfft_sR_f32_len1024;
56 | extern const arm_cfft_instance_f32 arm_cfft_sR_f32_len2048;
57 | extern const arm_cfft_instance_f32 arm_cfft_sR_f32_len4096;
58 |
59 | extern const arm_cfft_instance_q31 arm_cfft_sR_q31_len16;
60 | extern const arm_cfft_instance_q31 arm_cfft_sR_q31_len32;
61 | extern const arm_cfft_instance_q31 arm_cfft_sR_q31_len64;
62 | extern const arm_cfft_instance_q31 arm_cfft_sR_q31_len128;
63 | extern const arm_cfft_instance_q31 arm_cfft_sR_q31_len256;
64 | extern const arm_cfft_instance_q31 arm_cfft_sR_q31_len512;
65 | extern const arm_cfft_instance_q31 arm_cfft_sR_q31_len1024;
66 | extern const arm_cfft_instance_q31 arm_cfft_sR_q31_len2048;
67 | extern const arm_cfft_instance_q31 arm_cfft_sR_q31_len4096;
68 |
69 | extern const arm_cfft_instance_q15 arm_cfft_sR_q15_len16;
70 | extern const arm_cfft_instance_q15 arm_cfft_sR_q15_len32;
71 | extern const arm_cfft_instance_q15 arm_cfft_sR_q15_len64;
72 | extern const arm_cfft_instance_q15 arm_cfft_sR_q15_len128;
73 | extern const arm_cfft_instance_q15 arm_cfft_sR_q15_len256;
74 | extern const arm_cfft_instance_q15 arm_cfft_sR_q15_len512;
75 | extern const arm_cfft_instance_q15 arm_cfft_sR_q15_len1024;
76 | extern const arm_cfft_instance_q15 arm_cfft_sR_q15_len2048;
77 | extern const arm_cfft_instance_q15 arm_cfft_sR_q15_len4096;
78 |
79 | #endif
80 |
--------------------------------------------------------------------------------
/src/arm/stm32lx/bootloader.c:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2016-2019 Semtech (International) AG. All rights reserved.
2 | //
3 | // This file is subject to the terms and conditions defined in file 'LICENSE',
4 | // which is part of this source code package.
5 |
6 | #include "bootloader_impl.h"
7 | #include "update.h"
8 | #include "bootloader_hw.h"
9 | #include "sha2.h"
10 |
11 |
12 | // ------------------------------------------------
13 | // CRC-32
14 |
15 | static uint32_t boot_crc32 (void* buf, uint32_t nwords) {
16 | uint32_t* src = buf;
17 | uint32_t v;
18 |
19 | // enable crc peripheral
20 | RCC->AHBENR |= RCC_AHBENR_CRCEN;
21 | // reset crc peripheral, reverse bits on input and output (L0 only)
22 | CRC->CR = 0
23 | #if defined(STM32L0)
24 | | CRC_CR_REV_IN | CRC_CR_REV_OUT
25 | #endif
26 | | CRC_CR_RESET;
27 |
28 | while (nwords-- > 0) {
29 | v = *src++;
30 | #if defined(STM32L1)
31 | v = __rbit(v);
32 | #endif
33 | CRC->DR = v;
34 | }
35 | v = CRC->DR;
36 |
37 | // disable crc peripheral
38 | RCC->AHBENR &= ~RCC_AHBENR_CRCEN;
39 |
40 | #if defined(STM32L1)
41 | v = __rbit(v);
42 | #endif
43 |
44 | return ~v;
45 | }
46 |
47 |
48 | // ------------------------------------------------
49 | // LED macros
50 |
51 | #define _LED_INIT(p,n,on) do { \
52 | (p)->MODER = ((p)->MODER & ~(3 << (2 * (n)))) | (!!(on) << (2 * (n))); /* output */ \
53 | (p)->PUPDR = ((p)->PUPDR & ~(3 << (2 * (n)))) | (0 << (2 * (n))); /* no pull-up/down */ \
54 | (p)->OTYPER = ((p)->OTYPER & ~(1 << (1 * (n)))) | (0 << (1 * (n))); /* push-pull */ \
55 | (p)->OSPEEDR = ((p)->OSPEEDR & ~(3 << (2 * (n)))) | (0 << (2 * (n))); /* low speed */ \
56 | } while( 0 )
57 | #define LED_INIT(gpio) do { \
58 | GPIO_ENABLE(PORTN(gpio)); \
59 | _LED_INIT(PORT(gpio), PIN(gpio), 1); \
60 | } while( 0 )
61 | #define LED_DEINIT(gpio) do { \
62 | _LED_INIT(PORT(gpio), PIN(gpio), 0); \
63 | GPIO_DISABLE(PORTN(gpio)); \
64 | } while( 0 )
65 | #define LED_ON(gpio) do { SET_PIN(BOOT_LED_GPIO, (BOOT_LED_GPIO & GPIO_F_ACTLOW) ? 0 : 1); } while( 0 )
66 | #define LED_OFF(gpio) do { SET_PIN(BOOT_LED_GPIO, (BOOT_LED_GPIO & GPIO_F_ACTLOW) ? 1 : 0); } while( 0 )
67 |
68 |
69 | // ------------------------------------------------
70 | // Panic handler
71 |
72 | #if defined(BOOT_LED_GPIO)
73 |
74 | extern void delay (int); // provided by util.S
75 |
76 | // delay and refresh watchdog
77 | static void pause (int v) {
78 | // refresh watchdog
79 | IWDG->KR = 0xaaaa;
80 | // pause
81 | delay(v);
82 | }
83 |
84 | static void blink_value (uint32_t v) {
85 | // blink nibble-by-nibble
86 | // least-significant-nibble first, 0x0 -> 1 blink, 0xf -> 16 blinks
87 | do {
88 | uint32_t n = v & 0xf;
89 | do {
90 | LED_ON(BOOT_LED_GPIO);
91 | pause(6);
92 | LED_OFF(BOOT_LED_GPIO);
93 | pause(6);
94 | } while (n--);
95 | v >>= 4;
96 | pause(12);
97 | } while (v);
98 | }
99 | #endif
100 |
101 | // force inlining of reset call
102 | __attribute__((always_inline)) static void NVIC_SystemReset (void);
103 |
104 | __attribute__((noreturn))
105 | void boot_panic (uint32_t type, uint32_t reason, uint32_t addr) {
106 | // disable all interrupts
107 | __disable_irq();
108 | // startup MSI @2.1MHz
109 | RCC->ICSCR = (RCC->ICSCR & ~RCC_ICSCR_MSIRANGE) | RCC_ICSCR_MSIRANGE_5;
110 | RCC->CR |= RCC_CR_MSION;
111 | while ((RCC->CR & RCC_CR_MSIRDY) == 0);
112 | // switch clock source to MSI
113 | RCC->CFGR = (RCC->CFGR & ~RCC_CFGR_SW) | RCC_CFGR_SW_MSI;
114 | while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_MSI);
115 | // no flash wait states
116 | FLASH->ACR &= ~FLASH_ACR_LATENCY;
117 |
118 | #if defined(BOOT_LED_GPIO)
119 | LED_INIT(BOOT_LED_GPIO);
120 |
121 | int repeat = 3;
122 | while (repeat-- > 0) {
123 | // blink long
124 | LED_ON(BOOT_LED_GPIO);
125 | pause(30);
126 | LED_OFF(BOOT_LED_GPIO);
127 | pause(30);
128 | // blink type
129 | blink_value(type);
130 | pause(30);
131 | // blink reason
132 | blink_value(reason);
133 | pause(30);
134 | // blink address
135 | blink_value(addr);
136 | pause(30);
137 | }
138 | #endif
139 | NVIC_SystemReset();
140 | // not reached
141 | while (1);
142 | }
143 |
144 | __attribute__((noreturn, naked))
145 | static void fw_panic (uint32_t reason, uint32_t addr) {
146 | boot_panic(BOOT_PANIC_TYPE_FIRMWARE, reason, addr);
147 | }
148 |
149 |
150 | // ------------------------------------------------
151 | // Flash functions
152 |
153 | typedef void (*wr_fl_hp) (uint32_t*, const uint32_t*);
154 |
155 | typedef struct {
156 | boot_uphdr* fwup;
157 | wr_fl_hp wf_func;
158 | } up_ctx;
159 |
160 | static void unlock_flash (void) {
161 | // unlock flash registers
162 | FLASH->PEKEYR = 0x89ABCDEF; // FLASH_PEKEY1
163 | FLASH->PEKEYR = 0x02030405; // FLASH_PEKEY2
164 | // enable flash programming
165 | FLASH->PRGKEYR = 0x8C9DAEBF; // FLASH_PRGKEY1;
166 | FLASH->PRGKEYR = 0x13141516; // FLASH_PRGKEY2;
167 | // enable flash erase and half-page programming
168 | FLASH->PECR |= FLASH_PECR_PROG;
169 | }
170 |
171 | static void relock_flash (void) {
172 | FLASH->PECR |= FLASH_PECR_PELOCK;
173 | }
174 |
175 | static void check_eop (uint32_t panic_addr) {
176 | if (FLASH->SR & FLASH_SR_EOP) {
177 | FLASH->SR = FLASH_SR_EOP;
178 | } else {
179 | boot_panic(BOOT_PANIC_TYPE_BOOTLOADER,
180 | BOOT_PANIC_REASON_FLASH, panic_addr);
181 | }
182 | }
183 |
184 | extern uint32_t wr_fl_hp_begin; // provided by util.S
185 | extern uint32_t wr_fl_hp_end; // provided by util.S
186 |
187 | #define WR_FL_HP_WORDS (&wr_fl_hp_end - &wr_fl_hp_begin)
188 |
189 | static wr_fl_hp prep_wr_fl_hp (uint32_t* funcbuf) {
190 | for (int i = 0; i < WR_FL_HP_WORDS; i++) {
191 | funcbuf[i] = (&wr_fl_hp_begin)[i];
192 | }
193 | return THUMB_FUNC(funcbuf);
194 | }
195 |
196 | static void fl_write (wr_fl_hp wf_func, uint32_t* dst, const uint32_t* src, uint32_t nwords, bool erase) {
197 | while( nwords > 0 ) {
198 | if( erase && (((uintptr_t) dst) & 127) == 0 ) {
199 | // erase page
200 | FLASH->PECR |= FLASH_PECR_ERASE;
201 | *dst = 0;
202 | while( FLASH->SR & FLASH_SR_BSY );
203 | check_eop(2);
204 | FLASH->PECR &= ~FLASH_PECR_ERASE;
205 | }
206 | if( src ) {
207 | if( (((uintptr_t) dst) & 63) == 0 && nwords >= 16 ) {
208 | // write half page
209 | FLASH->PECR |= FLASH_PECR_FPRG;
210 | wf_func(dst, src);
211 | check_eop(3);
212 | FLASH->PECR &= ~FLASH_PECR_FPRG;
213 | src += 16;
214 | dst += 16;
215 | nwords -= 16;
216 | } else {
217 | // write word
218 | *dst++ = *src++;
219 | while( FLASH->SR & FLASH_SR_BSY );
220 | check_eop(4);
221 | nwords -= 1;
222 | }
223 | } else {
224 | if( nwords > 32 ) {
225 | dst += 32;
226 | nwords -= 32;
227 | } else {
228 | nwords = 0;
229 | }
230 | }
231 | }
232 | }
233 |
234 | static void write_flash (uint32_t* dst, const uint32_t* src, uint32_t nwords, bool erase) {
235 | uint32_t funcbuf[WR_FL_HP_WORDS];
236 | wr_fl_hp wf_func = prep_wr_fl_hp(funcbuf);
237 |
238 | unlock_flash();
239 | fl_write(wf_func, dst, src, nwords, erase);
240 | relock_flash();
241 | }
242 |
243 | static void ee_write (uint32_t* dst, uint32_t val) {
244 | *dst = val;
245 | while (FLASH->SR & FLASH_SR_BSY);
246 | }
247 |
248 |
249 | // ------------------------------------------------
250 | // Update glue functions
251 |
252 | uint32_t up_install_init (void* ctx, uint32_t fwsize, void** pfwdst, uint32_t tmpsize, void** ptmpdst, boot_fwhdr** pcurrentfw) {
253 | up_ctx* uc = ctx;
254 | if (!ISMULT_PAGE_SZ(fwsize) || fwsize > ((uintptr_t) uc->fwup - BOOT_FW_BASE)) {
255 | // new firmware is not multiple of page size or would overwrite update
256 | return BOOT_E_SIZE;
257 | }
258 |
259 | // assume dependency on current firmware when temp storage is requested
260 | if (tmpsize) {
261 | boot_fwhdr* fwhdr = (boot_fwhdr*) BOOT_FW_BASE;
262 | uint32_t fwmax = (fwsize > fwhdr->size) ? fwsize : fwhdr->size;
263 | if (!ISMULT_PAGE_SZ(tmpsize) || fwmax + tmpsize > ((uintptr_t) uc->fwup - BOOT_FW_BASE)) {
264 | return BOOT_E_SIZE;
265 | }
266 | }
267 |
268 | // set installation address for new firmware
269 | *pfwdst = (void*) BOOT_FW_BASE;
270 |
271 | // set address for temporary storage
272 | if (tmpsize && ptmpdst) {
273 | *ptmpdst = (unsigned char*) uc->fwup - tmpsize;
274 | }
275 |
276 | // set pointer to current firmware header
277 | if (pcurrentfw) {
278 | *pcurrentfw = (boot_fwhdr*) BOOT_FW_BASE;
279 | }
280 |
281 | return BOOT_OK;
282 | }
283 |
284 | void up_flash_wr_page (void* ctx, void* dst, void* src) {
285 | up_ctx* uc = ctx;
286 | #if defined(UPDATE_LED_GPIO)
287 | LED_ON(UPDATE_LED_GPIO);
288 | #endif
289 | fl_write(uc->wf_func, dst, src, FLASH_PAGE_SZ >> 2, true);
290 | #if defined(UPDATE_LED_GPIO)
291 | LED_OFF(UPDATE_LED_GPIO);
292 | #endif
293 | }
294 |
295 | void up_flash_unlock (void* ctx) {
296 | #if defined(UPDATE_LED_GPIO)
297 | LED_INIT(UPDATE_LED_GPIO);
298 | #endif
299 | unlock_flash();
300 | }
301 |
302 | void up_flash_lock (void* ctx) {
303 | relock_flash();
304 | #if defined(UPDATE_LED_GPIO)
305 | LED_DEINIT(UPDATE_LED_GPIO);
306 | #endif
307 | }
308 |
309 |
310 | // ------------------------------------------------
311 | // Update functions
312 |
313 | static void do_install (boot_uphdr* fwup) {
314 | uint32_t funcbuf[WR_FL_HP_WORDS];
315 | up_ctx uc = {
316 | .wf_func = prep_wr_fl_hp(funcbuf),
317 | .fwup = fwup,
318 | };
319 | if (update(&uc, fwup, true) != BOOT_OK) {
320 | boot_panic(BOOT_PANIC_TYPE_BOOTLOADER, BOOT_PANIC_REASON_UPDATE, 0);
321 | }
322 | }
323 |
324 | static bool check_update (boot_uphdr* fwup) {
325 | uint32_t flash_sz = FLASH_SZ();
326 |
327 | return ( ((intptr_t) fwup & 3) == 0
328 | && (intptr_t) fwup >= FLASH_BASE
329 | && sizeof(boot_uphdr) <= flash_sz - ((intptr_t) fwup - FLASH_BASE)
330 | && fwup->size >= sizeof(boot_uphdr)
331 | && (fwup->size & 3) == 0
332 | && fwup->size <= flash_sz - ((intptr_t) fwup - FLASH_BASE)
333 | && boot_crc32(((unsigned char*) fwup) + 8, (fwup->size - 8) >> 2) == fwup->crc
334 | && true /* TODO hardware id match */ );
335 | }
336 |
337 | static uint32_t set_update (void* ptr, hash32* hash) {
338 | uint32_t rv;
339 | if (ptr == NULL) {
340 | rv = BOOT_OK;
341 | } else {
342 | up_ctx uc = {
343 | .fwup = ptr,
344 | };
345 | rv = check_update((boot_uphdr*) ptr) ? update(&uc, ptr, false) : BOOT_E_SIZE;
346 | }
347 | if (rv == BOOT_OK) {
348 | boot_config* cfg = (boot_config*) BOOT_CONFIG_BASE;
349 | // unlock EEPROM
350 | FLASH->PEKEYR = 0x89ABCDEF; // FLASH_PEKEY1
351 | FLASH->PEKEYR = 0x02030405; // FLASH_PEKEY2
352 | // copy hash
353 | if (hash) {
354 | for (int i = 0; i < 8; i++) {
355 | ee_write(&cfg->hash.w[i], hash->w[i]);
356 | }
357 | }
358 | // set update pointer
359 | ee_write(&cfg->fwupdate1, (uint32_t) ptr);
360 | ee_write(&cfg->fwupdate2, (uint32_t) ptr);
361 | // relock EEPROM
362 | FLASH->PECR |= FLASH_PECR_PELOCK;
363 | }
364 | return rv;
365 | }
366 |
367 |
368 | // ------------------------------------------------
369 | // Bootloader main entry point
370 |
371 | void* bootloader (void) {
372 | boot_fwhdr* fwh = (boot_fwhdr*) BOOT_FW_BASE;
373 | boot_config* cfg = (boot_config*) BOOT_CONFIG_BASE;
374 |
375 | // check presence and integrity of firmware update
376 | if (cfg->fwupdate1 == cfg->fwupdate2) {
377 | boot_uphdr* fwup = (boot_uphdr*) cfg->fwupdate1;
378 | if (fwup != NULL && check_update(fwup)) {
379 | do_install(fwup);
380 | }
381 | }
382 |
383 | // verify integrity of current firmware
384 | if (fwh->size < sizeof(boot_fwhdr)
385 | || fwh->size > (FLASH_SZ() - (BOOT_FW_BASE - FLASH_BASE))
386 | || boot_crc32(((unsigned char*) fwh) + 8, (fwh->size - 8) >> 2) != fwh->crc) {
387 | boot_panic(BOOT_PANIC_TYPE_BOOTLOADER, BOOT_PANIC_REASON_CRC, 0);
388 | }
389 |
390 | // clear fwup pointer in EEPROM if set
391 | if (cfg->fwupdate1 != 0 || cfg->fwupdate2 != 0) {
392 | set_update(NULL, NULL);
393 | }
394 |
395 | // return entry point
396 | return (void*) fwh->entrypoint;
397 | }
398 |
399 |
400 | // ------------------------------------------------
401 | // Bootloader information table
402 | //
403 | // Version history:
404 | //
405 | // 0x100 - initial version
406 | // 0x101 - added wr_flash
407 | // 0x102 - added sha_256
408 | // 0x103 - support for self-contained LZ4 updates
409 | // 0x104 - support for LZ4 block-delta updates
410 | // 0x105 - wr_flash: allow flash erase-only operation by setting src=NULL
411 |
412 | __attribute__((section(".boot.boottab"))) const boot_boottab boottab = {
413 | .version = 0x108,
414 | .update = set_update,
415 | .panic = fw_panic,
416 | .crc32 = boot_crc32,
417 | .wr_flash = write_flash,
418 | .sha256 = sha256,
419 | };
420 |
--------------------------------------------------------------------------------
/src/arm/stm32lx/bootloader_hw.h:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2016-2019 Semtech (International) AG. All rights reserved.
2 | //
3 | // This file is subject to the terms and conditions defined in file 'LICENSE',
4 | // which is part of this source code package.
5 |
6 | #ifndef _bootloader_hw_h_
7 | #define _bootloader_hw_h_
8 |
9 | // ------------------------------------------------
10 | #if defined(STM32L0)
11 |
12 | #include "stm32l0xx.h"
13 |
14 | #define FLASH_SZ() (*((uint16_t*) 0x1FF8007C) << 10) // flash size register (L0x1 RM0377 28.1.1; L0x2 RM0376 33.1.1)
15 | #define FLASH_PAGE_SZ 128
16 | #define ROUND_PAGE_SZ(sz) (((sz) + (FLASH_PAGE_SZ - 1)) & ~(FLASH_PAGE_SZ - 1))
17 | #define ISMULT_PAGE_SZ(sz) (((sz) & (FLASH_PAGE_SZ - 1)) == 0)
18 |
19 | #define GPIO_RCC_ENR RCC->IOPENR
20 | #define GPIO_RCC_ENB(p) (((p) == 0) ? RCC_IOPENR_GPIOAEN \
21 | : ((p) == 1) ? RCC_IOPENR_GPIOBEN \
22 | : ((p) == 2) ? RCC_IOPENR_GPIOCEN \
23 | : 0)
24 |
25 |
26 | // ------------------------------------------------
27 | #elif defined(STM32L1)
28 |
29 | #include "stm32l1xx.h"
30 |
31 | #define GPIO_RCC_ENR RCC->AHBENR
32 | #define GPIO_RCC_ENB(p) (((p) == 0) ? RCC_AHBENR_GPIOAEN \
33 | : ((p) == 1) ? RCC_AHBENR_GPIOBEN \
34 | : ((p) == 2) ? RCC_AHBENR_GPIOCEN \
35 | : 0)
36 |
37 |
38 | // ------------------------------------------------
39 | #else
40 | #error "Unsupported MCU"
41 | #endif
42 |
43 |
44 | // ------------------------------------------------
45 | // GPIO definition
46 | #define GPIO(p,n,flags) ((((p)-'A') << 8) | (n) | (flags))
47 |
48 | #define GPIO_F_ACTLOW (1 << 16)
49 |
50 | // GPIO access
51 | #define GPIOx(pn) ((GPIO_TypeDef*) (GPIOA_BASE + (pn) * (GPIOB_BASE - GPIOA_BASE)))
52 | #define PORTN(gpio) ((gpio) >> 8 & 0xff)
53 | #define PORT(gpio) GPIOx(PORTN(gpio))
54 | #define PIN(gpio) ((gpio) & 0xff)
55 |
56 | #define SET_PIN(gpio, state) do { \
57 | PORT(gpio)->BSRR |= (1 << (PIN(gpio) + ((state) ? 0 : 16))); \
58 | } while (0)
59 |
60 | #define GPIO_ENABLE(p) do { GPIO_RCC_ENR |= GPIO_RCC_ENB(p); } while (0)
61 | #define GPIO_DISABLE(p) do { GPIO_RCC_ENR &= ~GPIO_RCC_ENB(p); } while (0)
62 |
63 | #endif
64 |
--------------------------------------------------------------------------------
/src/arm/stm32lx/bootloader_impl.h:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2016-2019 Semtech (International) AG. All rights reserved.
2 | //
3 | // This file is subject to the terms and conditions defined in file 'LICENSE',
4 | // which is part of this source code package.
5 |
6 | #ifndef _bootloader_impl_h_
7 | #define _bootloader_impl_h_
8 |
9 | #include "bootloader.h"
10 | #include "boottab.h"
11 |
12 | // Convert pointer to Thumb function (set least-significant bit)
13 | #define THUMB_FUNC(p) ((void*) (((intptr_t) (p)) | 1))
14 |
15 | extern uint32_t _ebl;
16 | #define BOOT_FW_BASE ((uint32_t) (&_ebl))
17 |
18 | #define BOOT_CONFIG_BASE DATA_EEPROM_BASE // XXX
19 | #define BOOT_CONFIG_SZ 64 // XXX
20 |
21 |
22 | // ------------------------------------------------
23 | // Bootloader configuration
24 |
25 | typedef struct {
26 | uint32_t fwupdate1; // 0x00 pointer to valid update
27 | uint32_t fwupdate2; // 0x04 pointer to valid update
28 | hash32 hash; // 0x08 SHA-256 hash of valid update
29 |
30 | uint8_t rfu[24]; // 0x28 RFU
31 | } boot_config;
32 |
33 | #endif
34 |
--------------------------------------------------------------------------------
/src/arm/stm32lx/boottab.h:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2016-2019 Semtech (International) AG. All rights reserved.
2 | //
3 | // This file is subject to the terms and conditions defined in file 'LICENSE',
4 | // which is part of this source code package.
5 |
6 | #ifndef _boottab_h_
7 | #define _boottab_h_
8 |
9 | #include "bootloader.h"
10 |
11 | // Bootloader information table on STM32
12 |
13 | typedef struct {
14 | uint32_t version; // version of boot loader (values below 256 are reserved for legacy bootloaders)
15 |
16 | __attribute__((noreturn))
17 | void (*panic) (uint32_t reason, uint32_t addr); // bootloader panic function
18 |
19 | uint32_t (*update) (void* ptr, hash32* hash); // function to set firmware update pointer
20 |
21 | uint32_t (*crc32) (void* buf, uint32_t nwords); // calculate CRC32
22 |
23 | void (*wr_flash) (uint32_t* dst, const uint32_t* src, // write flash
24 | uint32_t nwords, bool erase);
25 |
26 | void (*sha256) (uint32_t* hash, // SHA-256
27 | const uint8_t* msg, uint32_t len);
28 | } boot_boottab;
29 |
30 | #endif
31 |
--------------------------------------------------------------------------------
/src/arm/stm32lx/ld/STM32L0.ld:
--------------------------------------------------------------------------------
1 | _estack = ORIGIN(RAM) + LENGTH(RAM);
2 | _ebl = ORIGIN(BLFLASH) + LENGTH(BLFLASH);
3 |
4 | SECTIONS {
5 | .boot : {
6 | . = ALIGN(4);
7 | KEEP(*(.boot.isr_vector))
8 | . = ALIGN(4);
9 | *(.boot*)
10 | *(.text*)
11 | *(.rodata*)
12 | } >BLFLASH
13 | }
14 |
--------------------------------------------------------------------------------
/src/arm/stm32lx/ld/STM32L0xx8.ld:
--------------------------------------------------------------------------------
1 | MEMORY {
2 | RAM(xrw) : ORIGIN = 0x20000000, LENGTH = 8K
3 | BLFLASH(rx) : ORIGIN = 0x08000000, LENGTH = 12K
4 | FWFLASH(rx) : ORIGIN = 0x08000000 + 12K, LENGTH = 64K - 12K
5 | }
6 |
--------------------------------------------------------------------------------
/src/arm/stm32lx/ld/STM32L0xxB.ld:
--------------------------------------------------------------------------------
1 | MEMORY {
2 | RAM(xrw) : ORIGIN = 0x20000000, LENGTH = 20K
3 | BLFLASH(rx) : ORIGIN = 0x08000000, LENGTH = 12K
4 | FWFLASH(rx) : ORIGIN = 0x08000000 + 12K, LENGTH = 128K - 12K
5 | }
6 |
--------------------------------------------------------------------------------
/src/arm/stm32lx/ld/STM32L0xxZ.ld:
--------------------------------------------------------------------------------
1 | MEMORY {
2 | RAM(xrw) : ORIGIN = 0x20000000, LENGTH = 20K
3 | BLFLASH(rx) : ORIGIN = 0x08000000, LENGTH = 12K
4 | FWFLASH(rx) : ORIGIN = 0x08000000 + 12K, LENGTH = 192K - 12K
5 | }
6 |
--------------------------------------------------------------------------------
/src/arm/stm32lx/startup.S:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2016-2019 Semtech (International) AG. All rights reserved.
2 | //
3 | // This file is subject to the terms and conditions defined in file 'LICENSE',
4 | // which is part of this source code package.
5 |
6 | #include "bootloader.h"
7 |
8 | // --------------------------------------------
9 | // assembler settings
10 | .syntax unified
11 | .thumb
12 |
13 |
14 | // --------------------------------------------
15 | // Max. number of IRQn
16 | #if defined(STM32L0)
17 | #define MAX_IRQn 32 /* see PM0223, 2.3.4, pg. 29 */
18 | #elif defined(STM32L1)
19 | #define MAX_IRQn 68 /* see PM0056, 2.3.4, pg. 36 */
20 | #else
21 | #error "Unsupported MCU"
22 | #endif
23 |
24 |
25 | // --------------------------------------------
26 | // interrupt vector
27 | .section .boot.isr_vector,"a",%progbits
28 | .type isr_vector, %object
29 | isr_vector:
30 | .word _estack
31 | .word reset_handler
32 |
33 | .rept 14
34 | .word default_handler
35 | .endr
36 |
37 | .rept MAX_IRQn
38 | .word default_handler
39 | .endr
40 |
41 | .size isr_vector, .-isr_vector
42 |
43 |
44 | // --------------------------------------------
45 | // default handler
46 | .section .boot.default_handler,"ax",%progbits
47 | .thumb_func
48 | default_handler:
49 | movs r0, #4
50 | mov r1, lr
51 | tst r0, r1
52 | bne 1f
53 | mrs r2, msp
54 | b 2f
55 | 1: mrs r2, psp
56 | 2: ldr r2, [r2, #0x18] // return address
57 | movs r0, BOOT_PANIC_TYPE_EXCEPTION
58 | mrs r1, ipsr // exception number
59 | b boot_panic
60 |
61 | .size default_handler, .-default_handler
62 |
63 |
64 | // --------------------------------------------
65 | // reset handler (entry point)
66 | .section .boot.reset_handler,"ax",%progbits
67 | .thumb_func
68 | reset_handler:
69 | ldr r0, =_estack
70 | mov sp, r0
71 |
72 | // call boot loader
73 | bl bootloader
74 |
75 | // call entry point (returned from boot loader)
76 | mov r1, r0
77 | ldr r0, =boottab
78 | mov lr, pc
79 | mov pc, r1
80 |
81 | // should not be reached
82 | movs r0, BOOT_PANIC_TYPE_BOOTLOADER
83 | movs r1, BOOT_PANIC_REASON_FWRETURN
84 | movs r2, #0 // no return address
85 | b boot_panic
86 |
87 | .size reset_handler, .-reset_handler
88 |
--------------------------------------------------------------------------------
/src/arm/stm32lx/util.S:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2016-2019 Semtech (International) AG. All rights reserved.
2 | //
3 | // This file is subject to the terms and conditions defined in file 'LICENSE',
4 | // which is part of this source code package.
5 |
6 | #include "bootloader.h"
7 |
8 | // --------------------------------------------
9 | // assembler settings
10 | .syntax unified
11 | .thumb
12 |
13 |
14 | // --------------------------------------------
15 | // void delay (uint32_t length)
16 | .section .boot.delay,"ax",%progbits
17 | .thumb_func
18 | delay:
19 | lsls r0, r0, #16
20 | 1: subs r0, #1
21 | bne 1b
22 | bx lr
23 |
24 | .size delay, .-delay
25 | .global delay
26 |
27 |
28 | // --------------------------------------------
29 | // void wr_fl_hp (uint32_t* dst, const uint32_t* src)
30 | // write flash half-page (DO NOT CALL DIRECTLY!)
31 | // r0: dst*, r1: src*, r2-r5: scratch
32 | .section .boot.wr_fl_hp,"ax",%progbits
33 | wr_fl_hp_begin:
34 | .thumb_func
35 | wr_fl_hp:
36 | push {r4-r5, lr}
37 | // copy aligned data from src (RAM) to dst (FLASH)
38 | ldmia r1!, {r2-r5}
39 | stmia r0!, {r2-r5}
40 | ldmia r1!, {r2-r5}
41 | stmia r0!, {r2-r5}
42 | ldmia r1!, {r2-r5}
43 | stmia r0!, {r2-r5}
44 | ldmia r1!, {r2-r5}
45 | stmia r0!, {r2-r5}
46 | // wait for flash busy flag to clear
47 | ldr r0, 2f
48 | 1: ldr r1, [r0, #24]
49 | lsls r1, r1, #31
50 | bmi 1b
51 | // return
52 | pop {r4-r5, pc}
53 | .p2align(2)
54 | 2: .word 0x40022000
55 | wr_fl_hp_end:
56 |
57 | .size wr_fl_hp_begin, .-wr_fl_hp_begin
58 | .global wr_fl_hp_begin
59 | .global wr_fl_hp_end
60 |
--------------------------------------------------------------------------------
/src/arm/unicorn/bootloader.c:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2016-2019 Semtech (International) AG. All rights reserved.
2 | //
3 | // This file is subject to the terms and conditions defined in file 'LICENSE',
4 | // which is part of this source code package.
5 |
6 | #include
7 |
8 | #include "update.h"
9 | #include "boottab.h"
10 | #include "sha2.h"
11 |
12 |
13 | // ------------------------------------------------
14 | // Memory
15 |
16 | extern uint32_t _estack;
17 | extern uint32_t _ebl;
18 |
19 | #define RAM_BASE 0x10000000
20 | #define RAM_SIZE (16 * 1024)
21 | #define FLASH_BASE 0x20000000
22 | #define FLASH_SIZE (128 * 1024)
23 | #define EEPROM_BASE 0x30000000
24 | #define EEPROM_SIZE (8 * 1024)
25 |
26 | #define FLASH_PAGE_SZ 128
27 | #define ROUND_PAGE_SZ(sz) (((sz) + (FLASH_PAGE_SZ - 1)) & ~(FLASH_PAGE_SZ - 1))
28 | #define ISMULT_PAGE_SZ(sz) (((sz) & (FLASH_PAGE_SZ - 1)) == 0)
29 |
30 | #define FW_BASE ((uint32_t) (&_ebl))
31 | #define CONFIG_BASE EEPROM_BASE
32 |
33 |
34 | // ------------------------------------------------
35 | // CRC-32
36 |
37 | static void crc32 (uint32_t* pcrc, unsigned char* buf, uint32_t len) {
38 | int i;
39 | uint32_t byte, crc, mask;
40 |
41 | crc = ~(*pcrc);
42 | while (len-- != 0) {
43 | byte = *buf++;
44 | crc = crc ^ byte;
45 | for (i = 7; i >= 0; i--) {
46 | mask = -(crc & 1);
47 | crc = (crc >> 1) ^ (0xEDB88320 & mask);
48 | }
49 | }
50 | *pcrc = ~crc;
51 | }
52 |
53 | static uint32_t boot_crc32 (void* buf, uint32_t nwords) {
54 | uint32_t crc = 0;
55 | crc32(&crc, buf, nwords * 4);
56 | return crc;
57 | }
58 |
59 |
60 | // ------------------------------------------------
61 | // Panic
62 |
63 | static void svc (uint32_t id, uint32_t p1, uint32_t p2, uint32_t p3); // fwd decl
64 |
65 | __attribute__((noreturn, naked, noinline))
66 | static void fw_panic (uint32_t reason, uint32_t addr) {
67 | svc(BOOT_SVC_PANIC, BOOT_PANIC_TYPE_FIRMWARE, reason, addr);
68 | __builtin_unreachable();
69 | }
70 |
71 | __attribute__((noreturn, naked, noinline))
72 | static void boot_panic (uint32_t reason) {
73 | svc(BOOT_SVC_PANIC, BOOT_PANIC_TYPE_BOOTLOADER, reason, 0);
74 | __builtin_unreachable();
75 | }
76 |
77 |
78 | // ------------------------------------------------
79 | // Supervisor call
80 |
81 | __attribute__((naked, noinline))
82 | static void svc (uint32_t id, uint32_t p1, uint32_t p2, uint32_t p3) {
83 | asm("svc 0");
84 | // SVC call should not return, but might if not handled correctly
85 | boot_panic(0xdeadbeef);
86 | }
87 |
88 |
89 | // ------------------------------------------------
90 | // Flash functions
91 |
92 | void wr_flash (uint32_t* dst, const uint32_t* src, uint32_t nwords, bool erase) {
93 | if( ((uintptr_t) dst & 3) == 0 ) {
94 | while( nwords > 0 ) {
95 | if( erase && (((uintptr_t) dst) & (FLASH_PAGE_SZ-1)) == 0
96 | && (uintptr_t) dst >= FLASH_BASE && (uintptr_t) dst < (FLASH_BASE + FLASH_SIZE) ) {
97 | memset(dst, 0, FLASH_PAGE_SZ);
98 | }
99 | int wtw;
100 | if( nwords > (FLASH_PAGE_SZ >> 2)) {
101 | wtw = (FLASH_PAGE_SZ >> 2);
102 | } else {
103 | wtw = nwords;
104 | }
105 | if( src ) {
106 | memcpy(dst, src, wtw << 2);
107 | src += wtw;
108 | }
109 | dst += wtw;
110 | nwords -= wtw;
111 | }
112 | }
113 | }
114 |
115 |
116 | // ------------------------------------------------
117 | // Update glue functions
118 |
119 | typedef struct {
120 | boot_uphdr* fwup;
121 | bool unlocked;
122 | } up_ctx;
123 |
124 | uint32_t up_install_init (void* ctx, uint32_t fwsize, void** pfwdst, uint32_t tmpsize, void** ptmpdst, boot_fwhdr** pcurrentfw) {
125 | up_ctx* uc = ctx;
126 | if (!ISMULT_PAGE_SZ(fwsize) || fwsize > ((uintptr_t) uc->fwup - FW_BASE)) {
127 | // new firmware is not multiple of page size or would overwrite update
128 | return BOOT_E_SIZE;
129 | }
130 |
131 | // assume dependency on current firmware when temp storage is requested
132 | if (tmpsize) {
133 | boot_fwhdr* fwhdr = (boot_fwhdr*) FW_BASE;
134 | uint32_t fwmax = (fwsize > fwhdr->size) ? fwsize : fwhdr->size;
135 | if (!ISMULT_PAGE_SZ(tmpsize) || fwmax + ROUND_PAGE_SZ(tmpsize) > ((uintptr_t) uc->fwup - FW_BASE)) {
136 | return BOOT_E_SIZE;
137 | }
138 | }
139 |
140 | // set installation address for new firmware
141 | *pfwdst = (void*) FW_BASE;
142 |
143 | // set address for temporary storage
144 | if (tmpsize && ptmpdst) {
145 | *ptmpdst = (unsigned char*) uc->fwup - tmpsize;
146 | }
147 |
148 | // set pointer to current firmware header
149 | if (pcurrentfw) {
150 | *pcurrentfw = (boot_fwhdr*) FW_BASE;
151 | }
152 |
153 | return BOOT_OK;
154 | }
155 |
156 | void up_flash_wr_page (void* ctx, void* dst, void* src) {
157 | up_ctx* uc = ctx;
158 | if( uc->unlocked ) {
159 | wr_flash(dst, src, FLASH_PAGE_SZ >> 2, true);
160 | }
161 | }
162 |
163 | void up_flash_unlock (void* ctx) {
164 | up_ctx* uc = ctx;
165 | uc->unlocked = true;
166 | }
167 |
168 | void up_flash_lock (void* ctx) {
169 | up_ctx* uc = ctx;
170 | uc->unlocked = false;
171 | }
172 |
173 | static void ee_write (uint32_t* dst, uint32_t val) {
174 | if( (uintptr_t) dst >= EEPROM_BASE && (uintptr_t) dst < (EEPROM_BASE + EEPROM_SIZE) ) {
175 | *dst = val;
176 | }
177 | }
178 |
179 | // ------------------------------------------------
180 | // Update functions
181 |
182 | typedef struct {
183 | uint32_t fwupdate1; // 0x00 pointer to valid update
184 | uint32_t fwupdate2; // 0x04 pointer to valid update
185 | hash32 hash; // 0x08 SHA-256 hash of valid update
186 |
187 | uint8_t rfu[24]; // 0x28 RFU
188 | } boot_config;
189 |
190 | static void do_install (boot_uphdr* fwup) {
191 | up_ctx uc = {
192 | .fwup = fwup,
193 | };
194 | if (update(&uc, fwup, true) != BOOT_OK) {
195 | boot_panic(BOOT_PANIC_REASON_UPDATE);
196 | }
197 | }
198 |
199 | static bool check_update (boot_uphdr* fwup) {
200 | uint32_t flash_sz = FLASH_SIZE;
201 |
202 | return ( ((intptr_t) fwup & 3) == 0
203 | && (intptr_t) fwup >= FLASH_BASE
204 | && sizeof(boot_uphdr) <= flash_sz - ((intptr_t) fwup - FLASH_BASE)
205 | && fwup->size >= sizeof(boot_uphdr)
206 | && (fwup->size & 3) == 0
207 | && fwup->size <= flash_sz - ((intptr_t) fwup - FLASH_BASE)
208 | && boot_crc32(((unsigned char*) fwup) + 8, (fwup->size - 8) >> 2) == fwup->crc
209 | && true /* TODO hardware id match */ );
210 | }
211 |
212 | static uint32_t set_update (void* ptr, hash32* hash) {
213 | uint32_t rv;
214 | if( ptr == NULL ) {
215 | rv = BOOT_OK;
216 | } else {
217 | up_ctx uc = {
218 | .fwup = ptr,
219 | };
220 | rv = check_update((boot_uphdr*) ptr) ? update(&uc, ptr, false) : BOOT_E_SIZE;
221 | }
222 | if( rv == BOOT_OK ) {
223 | boot_config* cfg = (boot_config*) CONFIG_BASE;
224 | if( hash ) {
225 | for( int i = 0; i < 8; i++ ) {
226 | ee_write(&cfg->hash.w[i], hash->w[i]);
227 | }
228 | }
229 | // set update pointer
230 | ee_write(&cfg->fwupdate1, (uint32_t) ptr);
231 | ee_write(&cfg->fwupdate2, (uint32_t) ptr);
232 | }
233 | return rv;
234 | }
235 |
236 |
237 | // ------------------------------------------------
238 | // Bootloader information table
239 |
240 | static const boot_boottab boottab = {
241 | .version = 0x108,
242 | .update = set_update,
243 | .panic = fw_panic,
244 | .crc32 = boot_crc32,
245 | .svc = svc,
246 | .wr_flash = wr_flash,
247 | .sha256 = sha256,
248 | };
249 |
250 | // ------------------------------------------------
251 | // Bootloader main entry point
252 |
253 | void* bootloader (void) {
254 | boot_fwhdr* fwh = (boot_fwhdr*) FW_BASE;
255 | boot_config* cfg = (boot_config*) CONFIG_BASE;
256 |
257 | // check presence and integrity of firmware update
258 | if (cfg->fwupdate1 == cfg->fwupdate2) {
259 | boot_uphdr* fwup = (boot_uphdr*) cfg->fwupdate1;
260 | if (fwup != NULL && check_update(fwup)) {
261 | do_install(fwup);
262 | }
263 | }
264 |
265 | // verify integrity of current firmware
266 | if (fwh->size < sizeof(boot_fwhdr)
267 | || fwh->size > (FLASH_SIZE - (FW_BASE - FLASH_BASE))
268 | || boot_crc32(((unsigned char*) fwh) + 8, (fwh->size - 8) >> 2) != fwh->crc) {
269 | boot_panic(BOOT_PANIC_REASON_CRC);
270 | }
271 |
272 | // clear fwup pointer in EEPROM if set
273 | if (cfg->fwupdate1 != 0 || cfg->fwupdate2 != 0) {
274 | set_update(NULL, NULL);
275 | }
276 |
277 | // call entry point
278 | ((void (*) (const boot_boottab*)) fwh->entrypoint)(&boottab);
279 |
280 | // not reached
281 | boot_panic(BOOT_PANIC_REASON_FWRETURN);
282 | }
283 |
284 |
285 | // ------------------------------------------------
286 | // Bootloader header
287 |
288 | __attribute__((section(".boot.header"))) const struct {
289 | uint32_t init_sp;
290 | uint32_t init_pc;
291 | } boothdr = {
292 | .init_sp = (uint32_t) &_estack,
293 | .init_pc = (uint32_t) bootloader,
294 | };
295 |
--------------------------------------------------------------------------------
/src/arm/unicorn/bootloader_impl.h:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2016-2019 Semtech (International) AG. All rights reserved.
2 | //
3 | // This file is subject to the terms and conditions defined in file 'LICENSE',
4 | // which is part of this source code package.
5 |
6 | #ifndef _bootloader_impl_h_
7 | #define _bootloader_impl_h_
8 |
9 | #include "bootloader.h"
10 | #include "boottab.h"
11 |
12 | extern uint32_t _ebl;
13 | #define BOOT_FW_BASE ((uint32_t) (&_ebl))
14 |
15 | #define BOOT_CONFIG_BASE 0x30000000
16 | #define BOOT_CONFIG_SZ 64
17 |
18 |
19 | // ------------------------------------------------
20 | // Bootloader configuration
21 |
22 | typedef struct {
23 | uint32_t fwupdate1; // 0x00 pointer to valid update
24 | uint32_t fwupdate2; // 0x04 pointer to valid update
25 | hash32 hash; // 0x08 SHA-256 hash of valid update
26 |
27 | uint8_t rfu[24]; // 0x28 RFU
28 | } boot_config;
29 |
30 | #endif
31 |
--------------------------------------------------------------------------------
/src/arm/unicorn/boottab.h:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2016-2019 Semtech (International) AG. All rights reserved.
2 | //
3 | // This file is subject to the terms and conditions defined in file 'LICENSE',
4 | // which is part of this source code package.
5 |
6 | #ifndef _boottab_h_
7 | #define _boottab_h_
8 |
9 | #include "bootloader.h"
10 |
11 | // Bootloader information table on unicorn
12 |
13 | typedef struct {
14 | uint32_t version; // version of boot loader
15 | __attribute__((noreturn))
16 | void (*panic) (uint32_t reason, uint32_t addr); // bootloader panic function
17 | uint32_t (*update) (void* ptr, hash32* hash); // function to set firmware update pointer
18 | uint32_t (*crc32) (void* buf, uint32_t nwords); // calculate CRC32
19 | void* svc; // supervisor call
20 | void (*wr_flash) (uint32_t* dst, const uint32_t* src, // write flash
21 | uint32_t nwords, bool erase);
22 | void (*sha256) (uint32_t* hash, // SHA-256
23 | const uint8_t* msg, uint32_t len);
24 | } boot_boottab;
25 |
26 |
27 | // Supervisor call IDs
28 |
29 | enum {
30 | BOOT_SVC_PANIC, // panic: p1=type, p2=reason, p3=addr
31 |
32 | BOOT_SVC_FWBASE = 0x80 // all supervisor call ids below are reserved for bootloader
33 | };
34 |
35 | #endif
36 |
--------------------------------------------------------------------------------
/src/arm/unicorn/ld/bootloader.ld:
--------------------------------------------------------------------------------
1 | _estack = ORIGIN(RAM) + LENGTH(RAM);
2 | _ebl = ORIGIN(BLFLASH) + LENGTH(BLFLASH);
3 |
4 | SECTIONS {
5 | .boot : {
6 | . = ALIGN(4);
7 | KEEP(*(.boot.header))
8 | . = ALIGN(4);
9 | *(.boot*)
10 | *(.text*)
11 | *(.rodata*)
12 | } >BLFLASH
13 | }
14 |
--------------------------------------------------------------------------------
/src/arm/unicorn/ld/mem.ld:
--------------------------------------------------------------------------------
1 | MEMORY {
2 | RAM(xrw) : ORIGIN = 0x10000000, LENGTH = 16K
3 | BLFLASH(rx) : ORIGIN = 0x20000000, LENGTH = 4K
4 | FWFLASH(rx) : ORIGIN = 0x20000000 + 4K, LENGTH = 128K - 4K
5 | }
6 |
--------------------------------------------------------------------------------
/src/common/.gitignore:
--------------------------------------------------------------------------------
1 | sha2test
2 |
--------------------------------------------------------------------------------
/src/common/Makefile:
--------------------------------------------------------------------------------
1 | sha2test: sha2.c
2 | gcc -DSHA2_TEST $< -o $@
3 |
4 |
5 | clean:
6 | rm -f *.o sha2test
7 |
8 | .PHONY: clean
9 |
--------------------------------------------------------------------------------
/src/common/bootloader.h:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2016-2019 Semtech (International) AG. All rights reserved.
2 | //
3 | // This file is subject to the terms and conditions defined in file 'LICENSE',
4 | // which is part of this source code package.
5 |
6 | #ifndef _bootloader_h_
7 | #define _bootloader_h_
8 |
9 |
10 | // This is the public "API" of the bootloader,
11 | // i.e. the way the firmware and outside world
12 | // interact with it. Since a bootloader doesn't
13 | // change once installed and deployed, utmost
14 | // care must be taken when modifying this API!
15 |
16 |
17 | // Panic types
18 | #define BOOT_PANIC_TYPE_EXCEPTION 0 // Exception handler
19 | #define BOOT_PANIC_TYPE_BOOTLOADER 1 // Bootloader (reason codes see below)
20 | #define BOOT_PANIC_TYPE_FIRMWARE 2 // Firmware (reason codes are application defined)
21 |
22 |
23 | // Panic reason codes for type bootloader
24 | #define BOOT_PANIC_REASON_FWRETURN 0 // firmware returned unexpectedly
25 | #define BOOT_PANIC_REASON_CRC 1 // firmware CRC verification failed
26 | #define BOOT_PANIC_REASON_FLASH 2 // error writing flash
27 | #define BOOT_PANIC_REASON_UPDATE 3 // error updating firmware
28 |
29 |
30 | // Update type codes
31 | #define BOOT_UPTYPE_PLAIN 0 // plain update
32 | #define BOOT_UPTYPE_LZ4 1 // lz4-compressed self-contained update
33 | #define BOOT_UPTYPE_LZ4DELTA 2 // lz4-compressed block-delta update
34 |
35 |
36 | // Magic numbers
37 | #define BOOT_MAGIC_SIZE 0xff1234ff // place-holder for firmware size
38 |
39 |
40 | #ifndef ASSEMBLY
41 |
42 | #include
43 | #include
44 | #include
45 |
46 |
47 | // Bootloader return values (don't change values!)
48 | enum {
49 | BOOT_OK,
50 | BOOT_E_GENERAL, // general error
51 | BOOT_E_NOIMPL, // not implemented error
52 | BOOT_E_SIZE, // size error
53 | };
54 |
55 |
56 | // SHA-256 hash
57 | typedef union {
58 | uint8_t b[32];
59 | uint32_t w[8];
60 | } hash32;
61 |
62 | _Static_assert(sizeof(hash32) == 32, "sizeof(hash32) must be 32");
63 |
64 |
65 | // Firmware header
66 | typedef struct {
67 | uint32_t crc; // firmware CRC
68 | uint32_t size; // firmware size (in bytes, including this header)
69 | /* -- everything below until end (size-8) is included in CRC -- */
70 | uint32_t entrypoint; // address of entrypoint
71 | } boot_fwhdr;
72 |
73 | _Static_assert(sizeof(boot_fwhdr) == 12, "sizeof(boot_fwhdr) must be 12");
74 |
75 |
76 | // Hardware identifier (EUI-48, native byte order)
77 | typedef union {
78 | struct __attribute__((packed)) {
79 | uint32_t a;
80 | uint16_t b;
81 | };
82 | uint8_t bytes[6];
83 | } eui48;
84 |
85 | _Static_assert(sizeof(eui48) == 6, "sizeof(eui48) must be 6");
86 |
87 | static inline uint64_t eui2int (eui48* eui) {
88 | #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
89 | return ((uint64_t) eui->b << 32) | eui->a;
90 | #else
91 | return ((uint64_t) eui->a << 16) | eui->b;
92 | #endif
93 | }
94 |
95 |
96 | // Update header
97 | typedef struct {
98 | uint32_t crc; // update CRC
99 | uint32_t size; // update size (in bytes, including this header)
100 | /* -- everything below until end (size-8) is included in CRC -- */
101 | uint32_t fwcrc; // firmware CRC (once unpacked)
102 | uint32_t fwsize; // firmware size (in bytes, including header)
103 | eui48 hwid; // hardware target
104 | uint8_t uptype; // update type
105 | uint8_t rfu; // RFU
106 | } boot_uphdr;
107 |
108 | _Static_assert(sizeof(boot_uphdr) == 24, "sizeof(boot_uphdr) must be 24");
109 |
110 | // Update delta header
111 | typedef struct {
112 | uint32_t refcrc; // referenced firmware CRC
113 | uint32_t refsize; // referenced firmware size
114 | uint32_t blksize; // block size (multiple of flash page size, e.g. 4096)
115 | } boot_updeltahdr;
116 |
117 | _Static_assert(sizeof(boot_updeltahdr) == 12, "sizeof(boot_updeltahdr) must be 12");
118 |
119 | // Update delta block
120 | typedef struct __attribute__((packed)) {
121 | uint32_t hash[2]; // block hash (sha256[0-7])
122 | uint8_t blkidx; // block number
123 | uint8_t dictidx; // dictionary block number
124 | uint16_t dictlen; // length of dictionary data (in bytes)
125 | uint16_t lz4len; // length of lz4-compressed block data (in bytes, up to block size)
126 | uint8_t lz4data[]; // lz4-compressed block data
127 | } boot_updeltablk;
128 |
129 | _Static_assert(sizeof(boot_updeltablk) == 14, "sizeof(boot_updeltablk) must be 14");
130 |
131 | #endif
132 | #endif
133 |
--------------------------------------------------------------------------------
/src/common/lz4.c:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2016-2019 Semtech (International) AG. All rights reserved.
2 | //
3 | // This file is subject to the terms and conditions defined in file 'LICENSE',
4 | // which is part of this source code package.
5 |
6 | // The same code can be used for bootloader,
7 | // mkupdate tool, or standalone test
8 |
9 | #include
10 | #include "lz4.h"
11 | #include "update.h"
12 |
13 |
14 | // ------------------------------------------------
15 | // LZ4 decompression function with flash writing
16 | // and page-buffer support
17 |
18 | #ifdef LZ4_PAGEBUFFER_SZ
19 | #if ((LZ4_PAGEBUFFER_SZ & 3) != 0) || ((LZ4_PAGEBUFFER_SZ & (LZ4_PAGEBUFFER_SZ - 1)) != 0)
20 | #error "LZ4_PAGEBUFFER_SZ must be a multiple of 4 and a power of 2"
21 | #endif
22 | #endif
23 |
24 | typedef struct {
25 | unsigned char* dst;
26 | int dstlen;
27 | unsigned char* dictend;
28 | #ifdef LZ4_PAGEBUFFER_SZ
29 | uint32_t pagebuf[LZ4_PAGEBUFFER_SZ / 4];
30 | void* ctx;
31 | #endif
32 | } lz4state;
33 |
34 | // store byte in output buffer (negative b is match offset, else literal)
35 | // auto-flush buffer on page boundaries
36 | static void putbyte (lz4state* z, int b) {
37 | #ifdef LZ4_PAGEBUFFER_SZ
38 | int pageoff = z->dstlen & (LZ4_PAGEBUFFER_SZ - 1);
39 | // check for match reference
40 | if (b < 0) { // use referenced byte at distance 1..65535
41 | b = (pageoff+b >= 0) ?
42 | ((unsigned char*) z->pagebuf)[pageoff + b] : // referenced byte in page buffer
43 | ((z->dstlen + b < 0) ? z->dictend[z->dstlen + b] : z->dst[z->dstlen + b]); // referenced byte in dict or in previous output
44 | }
45 | // store byte in page buffer
46 | ((unsigned char*) z->pagebuf)[pageoff] = (unsigned char) b;
47 | // flush page when last byte is set
48 | if (pageoff == (LZ4_PAGEBUFFER_SZ - 1)) {
49 | // z->dst+z->dstlen still points to current page!
50 | up_flash_wr_page(z->ctx, (z->dst + (z->dstlen & ~(LZ4_PAGEBUFFER_SZ - 1))), z->pagebuf);
51 | }
52 | #else
53 | z->dst[z->dstlen] = (b < 0) ? ((z->dstlen + b < 0) ? z->dictend[z->dstlen + b] : z->dst[z->dstlen + b]) : (unsigned char) b;
54 | #endif
55 | z->dstlen++;
56 | }
57 |
58 | // decompress from src to dst optionally using dict, return uncompressed size
59 | // depending on configuration the uncompressed data is written directly or
60 | // buffered to ram, or buffered to flash
61 | // if buffering is used, the last page will be padded with FF
62 | int lz4_decompress (void* ctx, unsigned char* src, int srclen, unsigned char* dst, unsigned char* dict, int dictlen) {
63 | unsigned char* srcend = src + srclen;
64 | lz4state z;
65 |
66 | // init state
67 | z.dst = dst;
68 | z.dstlen = 0;
69 | z.dictend = dict + dictlen;
70 | #ifdef LZ4_PAGEBUFFER_SZ
71 | z.ctx = ctx;
72 | #endif
73 |
74 | // decode sequences
75 | while (src < srcend) {
76 | // get token
77 | unsigned char token = *src++;
78 | // get literal length
79 | int l, len = token >> 4;
80 | if (len == 15) do { l = *src++; len += l; } while (l == 255);
81 | // copy literals
82 | while (len--) {
83 | putbyte(&z, *src++);
84 | }
85 | if (src < srcend) { // last sequence is incomplete and stops after the literals
86 | // get offset
87 | int offset = *src++;
88 | offset = (*src++ << 8) | offset; // 16-bit LSB-first
89 | // get match length
90 | len = token & 0x0F;
91 | if (len == 15) do { l = *src++; len += l; } while(l == 255);
92 | len += 4; // minmatch
93 | // copy matches from output stream or from dict
94 | while (len--) {
95 | putbyte(&z, -offset);
96 | }
97 | }
98 | }
99 |
100 | // fill and flush last page
101 | int n = z.dstlen;
102 | #ifdef LZ4_PAGEBUFFER_SZ
103 | while (z.dstlen & (LZ4_PAGEBUFFER_SZ - 1)) {
104 | putbyte(&z, 0xFF);
105 | }
106 | #endif
107 | return n;
108 | }
109 |
110 |
111 | #ifdef LZ4_standalone
112 | // ------------------------------------------------
113 | // Standalone test program
114 | // gcc lz4.c -DLZ4_standalone -DLZ4_compress -o lz4 -llz4 -Wall
115 |
116 | #include
117 | #include
118 |
119 | // compress src buffer to dst buffer optionally using dict buffer, return compressed size
120 | int lz4_compress (unsigned char* src, int srclen, unsigned char* dict, int dictlen, unsigned char* dst, int dstlen) {
121 | unsigned char buf[srclen+64];
122 | LZ4_streamHC_t* lz4;
123 |
124 | // init LZ4 stream
125 | if( (lz4 = LZ4_createStreamHC()) == NULL ) {
126 | return -1;
127 | }
128 | LZ4_resetStreamHC(lz4, 9);
129 |
130 | // set dictionary
131 | if(dictlen) {
132 | LZ4_loadDictHC(lz4, (char*)dict, dictlen);
133 | }
134 |
135 | // compress
136 | dstlen = LZ4_compress_HC_continue(lz4, (char*)src, (char*)dst, srclen, dstlen);
137 | LZ4_freeStreamHC(lz4);
138 |
139 | // verify
140 | int len = lz4_decompress(dst, dstlen, buf, dict, dictlen);
141 | if(len != srclen || memcmp(buf, src, srclen) != 0) {
142 | return -1;
143 | }
144 |
145 | return dstlen;
146 | }
147 |
148 | // static buffers
149 | static unsigned char data[1024*1024], dict[1024*1024], zdata[1024*1024];
150 |
151 | int main (int argc, char **argv) {
152 | int datalen, dictlen = 0, zlen;
153 | FILE *fp;
154 |
155 | // check usage
156 | if (argc < 3) {
157 | printf("usage %s: []\n", argv[0]);
158 | return 1;
159 | }
160 |
161 | // load input file
162 | if ((fp = fopen(argv[1], "rb")) == NULL) {
163 | printf("can't open input file '%s'\n", argv[1]);
164 | return 1;
165 | }
166 | datalen = fread(data, 1, sizeof(data), fp);
167 | if (!feof(fp)) {
168 | printf("input file too large!\n");
169 | fclose(fp);
170 | return 1;
171 | }
172 | fclose(fp);
173 | printf("input file '%s': %d bytes\n", argv[1], datalen);
174 |
175 | // load dictionary file
176 | if (argc == 4) {
177 | if ((fp = fopen(argv[3], "rb")) == NULL) {
178 | printf("can't open dictionary file '%s'\n", argv[3]);
179 | return 1;
180 | }
181 | dictlen = fread(dict, 1, sizeof(dict), fp);
182 | if (!feof(fp)) {
183 | printf("dictionary file too large!\n");
184 | fclose(fp);
185 | return 1;
186 | }
187 | fclose(fp);
188 | printf("dictionary file '%s': %d bytes\n", argv[3], dictlen);
189 | }
190 |
191 | // compress with liblz4hc, verify with own decompressor
192 | if ((zlen = lz4_compress(data, datalen, dict, dictlen, zdata, sizeof(zdata))) < 0) {
193 | printf("compression / verification failed!\n");
194 | return 1;
195 | }
196 |
197 | // write output file
198 | if ((fp = fopen(argv[2], "wb")) == NULL ||
199 | fwrite(zdata, zlen, 1, fp) != 1 ||
200 | fclose(fp)) {
201 | printf("cannot write output file '%s'\n", argv[2]);
202 | return 1;
203 | }
204 | printf("output file '%s': %d bytes\n", argv[2], zlen);
205 |
206 | // print results
207 | printf("compression: %d / %d = %d%%\n", zlen, datalen, zlen*100/datalen);
208 | return 0;
209 | }
210 | #endif
211 |
--------------------------------------------------------------------------------
/src/common/lz4.h:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2016-2019 Semtech (International) AG. All rights reserved.
2 | //
3 | // This file is subject to the terms and conditions defined in file 'LICENSE',
4 | // which is part of this source code package.
5 |
6 | #ifndef _lz4_h_
7 | #define _lz4_h_
8 |
9 | int lz4_decompress (void* ctx, unsigned char* src, int srclen, unsigned char* dst, unsigned char* dict, int dictlen);
10 |
11 | #endif
12 |
--------------------------------------------------------------------------------
/src/common/sha2.c:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2016-2019 Semtech (International) AG. All rights reserved.
2 | //
3 | // This file is subject to the terms and conditions defined in file 'LICENSE',
4 | // which is part of this source code package.
5 |
6 | #include
7 |
8 | #include "sha2.h"
9 |
10 | #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
11 | #define ENDIAN_n2b32(x) __builtin_bswap32(x)
12 | #else
13 | #define ENDIAN_n2b32(x) (x)
14 | #endif
15 |
16 | // ------------------------------------------------
17 | // SHA-256
18 |
19 | #define ROR(a,b) (((a) >> (b)) | ((a) << (32 - (b))))
20 |
21 | #define CH(x,y,z) (((x) & (y)) ^ (~(x) & (z)))
22 | #define MAJ(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
23 | #define EP0(x) (ROR(x, 2) ^ ROR(x, 13) ^ ROR(x, 22))
24 | #define EP1(x) (ROR(x, 6) ^ ROR(x, 11) ^ ROR(x, 25))
25 | #define SIG0(x) (ROR(x, 7) ^ ROR(x, 18) ^ ((x) >> 3))
26 | #define SIG1(x) (ROR(x, 17) ^ ROR(x, 19) ^ ((x) >> 10))
27 |
28 | static void sha256_do (uint32_t* state, const uint8_t* block) {
29 | static const uint32_t K[64] = {
30 | 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
31 | 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
32 | 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
33 | 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
34 | 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
35 | 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
36 | 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
37 | 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
38 | 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
39 | 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
40 | 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
41 | 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
42 | 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
43 | 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
44 | 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
45 | 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
46 | };
47 |
48 | uint32_t a, b, c, d, e, f, g, h, i, j, t1, t2, w[64];
49 |
50 | for (i = 0, j = 0; i < 16; i++, j += 4) {
51 | w[i] = (block[j] << 24) | (block[j + 1] << 16) | (block[j + 2] << 8) | (block[j + 3]);
52 | }
53 | for ( ; i < 64; i++) {
54 | w[i] = SIG1(w[i - 2]) + w[i - 7] + SIG0(w[i - 15]) + w[i - 16];
55 | }
56 |
57 | a = state[0];
58 | b = state[1];
59 | c = state[2];
60 | d = state[3];
61 | e = state[4];
62 | f = state[5];
63 | g = state[6];
64 | h = state[7];
65 |
66 | for (i = 0; i < 64; i++) {
67 | t1 = h + EP1(e) + CH(e, f, g) + K[i] + w[i];
68 | t2 = EP0(a) + MAJ(a, b, c);
69 | h = g;
70 | g = f;
71 | f = e;
72 | e = d + t1;
73 | d = c;
74 | c = b;
75 | b = a;
76 | a = t1 + t2;
77 | }
78 |
79 | state[0] += a;
80 | state[1] += b;
81 | state[2] += c;
82 | state[3] += d;
83 | state[4] += e;
84 | state[5] += f;
85 | state[6] += g;
86 | state[7] += h;
87 | }
88 |
89 | #undef ROR
90 | #undef CH
91 | #undef MAJ
92 | #undef EP0
93 | #undef EP1
94 | #undef SIG0
95 | #undef SIG1
96 |
97 | void sha256 (uint32_t* hash, const uint8_t* msg, uint32_t len) {
98 | uint32_t state[8] = {
99 | 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
100 | 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19
101 | };
102 |
103 | uint32_t bitlen = len << 3;
104 | while (1) {
105 | if (len < 64) {
106 | union {
107 | uint8_t bytes[64];
108 | uint32_t words[16];
109 | } tmp;
110 | memset(tmp.words, 0, sizeof(tmp));
111 | memcpy(tmp.bytes, msg, len);
112 | tmp.bytes[len] = 0x80;
113 | if (len < 56) {
114 | last:
115 | tmp.words[15] = ENDIAN_n2b32(bitlen);
116 | sha256_do(state, tmp.bytes);
117 | for (int i = 0; i < 8; i++) {
118 | hash[i] = ENDIAN_n2b32(state[i]);
119 | }
120 | return;
121 | } else {
122 | sha256_do(state, tmp.bytes);
123 | memset(tmp.words, 0, sizeof(tmp));
124 | goto last;
125 | }
126 | } else {
127 | sha256_do(state, msg);
128 | msg += 64;
129 | len -= 64;
130 | }
131 | }
132 | }
133 |
134 | #ifdef SHA2_TEST
135 |
136 | #include
137 |
138 | static int readfully (int fd, unsigned char* buf, size_t bufsz) {
139 | while( bufsz ) {
140 | ssize_t n = read(fd, buf, bufsz);
141 | if( n <= 0 ) {
142 | return -1;
143 | }
144 | buf += n;
145 | bufsz -= n;
146 | }
147 | return 0;
148 | }
149 |
150 | static int writefully (int fd, unsigned char* buf, size_t bufsz) {
151 | while( bufsz ) {
152 | ssize_t n = write(fd, buf, bufsz);
153 | if( n <= 0 ) {
154 | return -1;
155 | }
156 | buf += n;
157 | bufsz -= n;
158 | }
159 | return 0;
160 | }
161 |
162 | int main (void) {
163 | unsigned char buf[128*1024];
164 | union {
165 | uint8_t bytes[32];
166 | uint32_t words[8];
167 | } hash;
168 | while( 1 ) {
169 | uint32_t sz;
170 | if( readfully(STDIN_FILENO, (unsigned char*) &sz, sizeof(uint32_t)) < 0
171 | || sz > sizeof(buf)
172 | || readfully(STDIN_FILENO, buf, sz) < 0 ) {
173 | break;
174 | }
175 | sha256(hash.words, buf, sz);
176 | writefully(STDOUT_FILENO, hash.bytes, 32);
177 | }
178 | return 0;
179 | }
180 |
181 | #endif
182 |
--------------------------------------------------------------------------------
/src/common/sha2.h:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2016-2019 Semtech (International) AG. All rights reserved.
2 | //
3 | // This file is subject to the terms and conditions defined in file 'LICENSE',
4 | // which is part of this source code package.
5 |
6 | #ifndef _sha2_h_
7 | #define _sha2_h_
8 |
9 | #include
10 |
11 | void sha256 (uint32_t* hash, const uint8_t* msg, uint32_t len);
12 |
13 | #endif
14 |
15 |
--------------------------------------------------------------------------------
/src/common/update.c:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2016-2019 Semtech (International) AG. All rights reserved.
2 | //
3 | // This file is subject to the terms and conditions defined in file 'LICENSE',
4 | // which is part of this source code package.
5 |
6 | #include "bootloader.h"
7 | #include "update.h"
8 | #include "sha2.h"
9 | #include "lz4.h"
10 |
11 | #if !defined(UP_PAGEBUFFER_SZ) || ((UP_PAGEBUFFER_SZ & 3) != 0) || ((UP_PAGEBUFFER_SZ & (UP_PAGEBUFFER_SZ - 1)) != 0)
12 | #error "UP_PAGEBUFFER_SZ must be defined as a multiple of 4 and a power of 2"
13 | #endif
14 |
15 | #define PB_WORDS (UP_PAGEBUFFER_SZ >> 2)
16 |
17 |
18 | // ------------------------------------------------
19 | // Update functions
20 |
21 | // write flash pages (src can be in flash too)
22 | static void flashcopy (void* ctx, uint32_t* dst, const uint32_t* src, uint32_t nwords) {
23 | while (nwords > 0) {
24 | uint32_t buf[PB_WORDS];
25 | int i, m = (nwords < PB_WORDS) ? nwords : PB_WORDS;
26 | nwords -= m;
27 | for (i = 0; i < m; i++) {
28 | buf[i] = *src++;
29 | }
30 | for (; i < PB_WORDS; i++) {
31 | buf[i] = 0; // pad last page with 0
32 | }
33 | up_flash_wr_page(ctx, dst, buf);
34 | dst += PB_WORDS;
35 | }
36 | }
37 |
38 | static uint32_t update_plain (void* ctx, boot_uphdr* fwup, bool install) {
39 | uint32_t* src = (uint32_t*) (fwup + 1);
40 | uint32_t* dst;
41 | uint32_t rv;
42 |
43 | // perform size check and get install address
44 | if ((rv = up_install_init(ctx, fwup->fwsize, (void**) &dst, 0, NULL, NULL)) != BOOT_OK) {
45 | return rv;
46 | }
47 |
48 | // copy new firmware to destination
49 | if (install) {
50 | up_flash_unlock(ctx);
51 | flashcopy(ctx, dst, src, fwup->fwsize >> 2);
52 | up_flash_lock(ctx);
53 | }
54 | return BOOT_OK;
55 | }
56 |
57 | // process LZ4-compressed self-contained update
58 | static uint32_t update_lz4 (void* ctx, boot_uphdr* fwup, bool install) {
59 | uint8_t* dst;
60 | uint8_t* src = (uint8_t*) fwup + sizeof(boot_uphdr);
61 | uint32_t srclen = fwup->size - sizeof(boot_uphdr);
62 | uint32_t lz4len = srclen - src[srclen-1]; // strip word padding
63 | uint32_t rv;
64 |
65 | // perform size check and get install address
66 | if ((rv = up_install_init(ctx, fwup->fwsize, (void**) &dst, 0, NULL, NULL)) != BOOT_OK) {
67 | return rv;
68 | }
69 |
70 | if (install) {
71 | up_flash_unlock(ctx);
72 | // uncompress new firmware and replace current firmware at destination
73 | lz4_decompress(ctx, src, lz4len, dst, NULL, 0);
74 | up_flash_lock(ctx);
75 | }
76 |
77 | return BOOT_OK;
78 | }
79 |
80 | static bool checkhash (const uint8_t* msg, uint32_t len, uint32_t* hash) {
81 | uint32_t tmp[8];
82 | sha256(tmp, msg, len);
83 | return (tmp[0] == hash[0] && tmp[1] == hash[1]);
84 | }
85 |
86 | // process LZ4-compressed block-delta update
87 | static uint32_t update_lz4delta (void* ctx, boot_uphdr* fwup, bool install) {
88 | boot_updeltahdr* dhdr = (boot_updeltahdr*) ((uint8_t*) fwup + sizeof(boot_uphdr));
89 | uint8_t* src = (uint8_t*) dhdr + sizeof(boot_updeltahdr);
90 | uint8_t* end = (uint8_t*) fwup + fwup->size;
91 | uint32_t blksize = dhdr->blksize;
92 | uint8_t* dst;
93 | uint8_t* tmp;
94 | boot_fwhdr* fwhdr;
95 | uint32_t rv;
96 |
97 | // perform size check and get install address and temp area
98 | if ((rv = up_install_init(ctx, fwup->fwsize, (void**) &dst, blksize, (void**) &tmp, &fwhdr)) != BOOT_OK) {
99 | return rv;
100 | }
101 |
102 | // check reference firmware crc and size before installing (will be overwritten during install)
103 | if (!install && (dhdr->refcrc != fwhdr->crc || dhdr->refsize != fwhdr->size)) {
104 | return BOOT_E_GENERAL;
105 | }
106 |
107 | // process delta blocks
108 | while (src < end) {
109 | boot_updeltablk* b = (boot_updeltablk*) src; // delta block
110 | uint32_t boff = b->blkidx * blksize;
111 | uint32_t doff = b->dictidx * blksize;
112 | if (boff > fwup->fwsize || doff + b->dictlen > dhdr->refsize) {
113 | return BOOT_E_SIZE;
114 | }
115 | uint8_t* baddr = dst + boff;
116 | uint32_t bsz = (fwup->fwsize - boff < blksize) ? fwup->fwsize - boff : blksize; // current block size (last block might be shorter)
117 | if (install) {
118 | // verify target block
119 | if (!checkhash(baddr, bsz, b->hash)) {
120 | up_flash_unlock(ctx);
121 | // verify temp block
122 | if (!checkhash(tmp, bsz, b->hash)) {
123 | // uncompress delta to temp block
124 | if (lz4_decompress(ctx, b->lz4data, b->lz4len, tmp, (uint8_t*) fwhdr + doff, b->dictlen) != bsz) {
125 | return BOOT_E_GENERAL; // unrecoverable error - should not happen!
126 | }
127 | // verify temp block
128 | if (!checkhash(tmp, bsz, b->hash)) {
129 | return BOOT_E_GENERAL; // unrecoverable error - should not happen!
130 | }
131 | }
132 | // copy temp block to target
133 | flashcopy(ctx, (uint32_t*) baddr, (uint32_t*) tmp, bsz >> 2);
134 | up_flash_lock(ctx);
135 | }
136 | }
137 | // advance to next delta block (4-aligned)
138 | src += (sizeof(boot_updeltablk) + b->lz4len + 3) & ~0x3;
139 | }
140 |
141 | return BOOT_OK;
142 | }
143 |
144 | uint32_t update (void* ctx, boot_uphdr* fwup, bool install) {
145 | // Note: The integrity of the update pointed to by fwup has
146 | // been verified at this point.
147 |
148 | switch (fwup->uptype) {
149 | case BOOT_UPTYPE_PLAIN:
150 | return update_plain(ctx, fwup, install);
151 | case BOOT_UPTYPE_LZ4:
152 | return update_lz4(ctx, fwup, install);
153 | case BOOT_UPTYPE_LZ4DELTA:
154 | return update_lz4delta(ctx, fwup, install);
155 | default:
156 | return BOOT_E_NOIMPL;
157 | }
158 | }
159 |
--------------------------------------------------------------------------------
/src/common/update.h:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2016-2019 Semtech (International) AG. All rights reserved.
2 | //
3 | // This file is subject to the terms and conditions defined in file 'LICENSE',
4 | // which is part of this source code package.
5 |
6 | #ifndef _update_h_
7 | #define _update_h_
8 |
9 | #include "bootloader.h"
10 |
11 | uint32_t update (void* ctx, boot_uphdr* fwup, bool install);
12 |
13 | // glue functions
14 | extern uint32_t up_install_init (void* ctx, uint32_t fwsize, void** pfwdst, uint32_t tmpsize, void** ptmpdst, boot_fwhdr** pcurrentfw);
15 | extern void up_flash_wr_page (void* ctx, void* dst, void* src);
16 | extern void up_flash_unlock (void* ctx);
17 | extern void up_flash_lock (void* ctx);
18 |
19 | #endif
20 |
--------------------------------------------------------------------------------
/tools/fwtool/.gitignore:
--------------------------------------------------------------------------------
1 | .mypy_cache
2 | __pycache__
3 |
--------------------------------------------------------------------------------
/tools/fwtool/signtool.py:
--------------------------------------------------------------------------------
1 | import sys
2 | import struct
3 | from Crypto.Hash import SHA256
4 | from Crypto.PublicKey import ECC
5 | from Crypto.Signature import DSS
6 |
7 | if len(sys.argv) != 5:
8 | print('usage: signtool UPFILE KEYFILE PASSPHRASE OUTFILE')
9 | else:
10 | upd = open(sys.argv[1], 'rb').read()
11 | usz = struct.unpack(' 0
30 | o += n
31 | self.proc.stdin.flush()
32 |
33 | def read(self, n):
34 | b = b''
35 | while len(b) < n:
36 | d = self.proc.stdout.read(n - len(b))
37 | assert len(d)
38 | b += d
39 | return b
40 |
41 | def digest(self, msg):
42 | self.write(struct.pack('I', len(msg)) + msg)
43 | return self.read(32)
44 |
45 | class SHAVS:
46 | class MsgTest:
47 | def __init__(self, m, h):
48 | self.m = m
49 | self.h = h
50 |
51 | def steps(self):
52 | return 1
53 |
54 | def run(self, hobj, pb):
55 | assert hobj.digest(self.m) == self.h
56 | pb.update(1)
57 |
58 | class MonteCarloTest:
59 | def __init__(self, seed):
60 | self.seed = seed
61 | self.mds = list()
62 |
63 | def steps(self):
64 | return 1000 * 100
65 |
66 | def addmd(self, ct, md):
67 | assert len(self.mds) == ct
68 | self.mds.append(md)
69 |
70 | def run(self, hobj, pb):
71 | h = self.seed
72 | for i in range(100):
73 | mc_1 = h
74 | mc_2 = h
75 | for _ in range(1000):
76 | msg = mc_2 + mc_1 + h
77 | mc_2 = mc_1
78 | mc_1 = h
79 | h = hobj.digest(msg)
80 | pb.update(1)
81 | assert h == self.mds[i]
82 |
83 | def __init__(self, zipfile, prefix, hobj):
84 | self.hobj = hobj
85 | self.tests = list()
86 | with zip.ZipFile(zipfile) as zf:
87 | for fn in zf.namelist():
88 | p = pathlib.Path(fn)
89 | if p.suffix == '.rsp' and p.name.startswith(prefix):
90 | with zf.open(fn) as f:
91 | d = {}
92 | for l in f:
93 | m = re.match(r'(\w+)\s*=\s*(\w+)', l.decode())
94 | if m:
95 | k,v = m.groups()
96 | if k == 'MD':
97 | if 'Seed' in d:
98 | # new Monte Carlo
99 | self.tests.append(SHAVS.MonteCarloTest(
100 | bytes.fromhex(d['Seed'])))
101 | if 'COUNT' in d:
102 | self.tests[-1].addmd(int(d['COUNT']), bytes.fromhex(v))
103 | else:
104 | self.tests.append(SHAVS.MsgTest(
105 | bytes.fromhex(d['Msg'])[:int(d['Len'])//8],
106 | bytes.fromhex(v)))
107 | d.clear()
108 | else:
109 | d[k] = v
110 |
111 | def run(self):
112 | steps = sum(t.steps() for t in self.tests)
113 | with tqdm.tqdm(total=steps) as pb:
114 | for t in self.tests:
115 | t.run(self.hobj, pb)
116 | print('All tests passed.')
117 |
118 | #SHAVS('shabytetestvectors.zip', 'SHA256', HashlibHash(hashlib.sha256)).run()
119 | SHAVS('shabytetestvectors.zip', 'SHA256', ProcessHash('../../src/common/sha2test')).run()
120 |
--------------------------------------------------------------------------------