Skip to content

Commit d32d315

Browse files
authored
minor tidying of hardware_rcp header; add an rcp_is_true() that is safe to use on RISC-V too (#2568)
1 parent 820a33a commit d32d315

File tree

2 files changed

+130
-112
lines changed

2 files changed

+130
-112
lines changed

src/rp2_common/hardware_rcp/include/hardware/rcp.h

Lines changed: 129 additions & 111 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,17 @@
1515
*/
1616

1717
// ----------------------------------------------------------------------------
18-
// RCP masks
19-
#if !PICO_RP2040
18+
// RCP instructions (this header is Arm-only)
19+
#if HAS_REDUNDANCY_COPROCESSOR
20+
#ifdef __riscv
21+
#error "HAS_REDUNDANCY_COPROCESSOR should be false on RISC-V"
22+
#endif
2023

24+
#define rcp_is_true(x) ((x) == RCP_MASK_TRUE)
2125
#define RCP_MASK_TRUE _u(0xa500a500)
2226
#define RCP_MASK_FALSE _u(0x00c300c3)
2327
#define RCP_MASK_INTXOR _u(0x96009600)
2428

25-
// RCP instructions (these instructions are Arm-only)
26-
#if HAS_REDUNDANCY_COPROCESSOR
2729
// ----------------------------------------------------------------------------
2830
// Macros and inline functions for use in C files
2931
#ifndef __ASSEMBLER__
@@ -86,6 +88,7 @@ static __rcpinline void rcp_salt_core1_nodelay(uint64_t salt) {
8688

8789
// Get a 32-bit canary value. `tag` must be a constant expression.
8890
#define rcp_canary_get(tag) ({ \
91+
static_assert(!((tag) & ~0xffu), "Tag out of range"); \
8992
uint32_t __canary_u32; \
9093
rcp_asm ( \
9194
"mrc p7, #0, %0, c%c1, c%c2, #1\n" \
@@ -96,6 +99,7 @@ static __rcpinline void rcp_salt_core1_nodelay(uint64_t salt) {
9699
})
97100

98101
#define rcp_canary_get_nodelay(tag) ({ \
102+
static_assert(!((tag) & ~0xffu), "Tag out of range"); \
99103
uint32_t __canary_u32; \
100104
rcp_asm ( \
101105
"mrc2 p7, #0, %0, c%c1, c%c2, #1\n" \
@@ -107,6 +111,7 @@ static __rcpinline void rcp_salt_core1_nodelay(uint64_t salt) {
107111

108112
// Assert that canary matches result of rcp_canary_get with the same tags:
109113
#define rcp_canary_check(tag, canary) ({ \
114+
static_assert(!((tag) & ~0xffu), "Tag out of range"); \
110115
rcp_asm ( \
111116
"mcr p7, #0, %0, c%c1, c%c2, #1\n" \
112117
: : "r" (canary), \
@@ -115,6 +120,7 @@ static __rcpinline void rcp_salt_core1_nodelay(uint64_t salt) {
115120
})
116121

117122
#define rcp_canary_check_nodelay(tag, canary) ({ \
123+
static_assert(!((tag) & ~0xffu), "Tag out of range"); \
118124
rcp_asm ( \
119125
"mcr2 p7, #0, %0, c%c1, c%c2, #1\n" \
120126
: : "r" (canary), \
@@ -141,6 +147,9 @@ static __rcpinline uint32_t rcp_canary_status_nodelay(void) {
141147
// ----------------------------------------------------------------------------
142148
// RCP Boolean instructions
143149

150+
// These instructions assert that all their arguments are valid booleans, in
151+
// addition to any other logical conditions
152+
144153
// Assert b is a valid boolean (0xa500a500u or 0x00c300c3u)
145154
static __rcpinline void rcp_bvalid(uint32_t b) {
146155
rcp_asm ("mcr p7, #1, %0, c0, c0, #0\n" : : "r" (b));
@@ -308,106 +317,8 @@ static __rcpinline __attribute__((noreturn)) void rcp_panic(void) {
308317
#else // __ASSEMBLER__
309318
#ifndef __riscv
310319

311-
// Assert b is a valid boolean (0xa500a500u or 0x00c300c3u)
312-
.macro rcp_bvalid r
313-
mcr p7, #1, \r , c0, c0, #0
314-
.endm
315-
316-
.macro rcp_bvalid_nodelay r
317-
mcr2 p7, #1, \r , c0, c0, #0
318-
.endm
319-
320-
// Assert b is true (0xa500a500u)
321-
.macro rcp_btrue r
322-
mcr p7, #2, \r , c0, c0, #0
323-
.endm
324-
325-
.macro rcp_btrue_nodelay r
326-
mcr2 p7, #2, \r , c0, c0, #0
327-
.endm
328-
329-
// Assert b is false (0x00c300c3u)
330-
.macro rcp_bfalse r
331-
mcr p7, #3, \r , c0, c0, #1
332-
.endm
333-
334-
.macro rcp_bfalse_nodelay r
335-
mcr2 p7, #3, \r , c0, c0, #1
336-
.endm
337-
338-
// Assert b0 and b1 are both valid booleans
339-
.macro rcp_b2valid b0, b1
340-
mcrr p7, #0, \b0 , \b1 , c8
341-
.endm
342-
343-
.macro rcp_b2valid_nodelay b0, b1
344-
mcrr2 p7, #0, \b0 , \b1 , c8
345-
.endm
346-
347-
// Assert b0 and b1 are both true
348-
.macro rcp_b2and b0, b1
349-
mcrr p7, #1, \b0 , \b1 , c0
350-
.endm
351-
352-
.macro rcp_b2and_nodelay b0, b1
353-
mcrr2 p7, #1, \b0 , \b1 , c0
354-
.endm
355-
356-
// Assert b0 and b1 are valid, and at least one is true
357-
.macro rcp_b2or b0, b1
358-
mcrr p7, #2, \b0 , \b1 , c0
359-
.endm
360-
361-
.macro rcp_b2or_nodelay b0, b1
362-
mcrr2 p7, #2, \b0 , \b1 , c0
363-
.endm
364-
365-
// Assert (b ^ mask) is a valid boolean
366-
.macro rcp_bxorvalid b, mask
367-
mcrr p7, #3, \b , \mask , c8
368-
.endm
369-
370-
.macro rcp_bxorvalid_nodelay b, mask
371-
mcrr2 p7, #3, \b , \mask , c8
372-
.endm
373-
374-
// Assert (b ^ mask) is true
375-
.macro rcp_bxortrue b, mask
376-
mcrr p7, #4, \b , \mask , c0
377-
.endm
378-
379-
.macro rcp_bxortrue_nodelay b, mask
380-
mcrr2 p7, #4, \b , \mask , c0
381-
.endm
382-
383-
// Assert (b ^ mask) is false
384-
.macro rcp_bxorfalse b, mask
385-
mcrr p7, #5, \b , \mask , c8
386-
.endm
387-
388-
.macro rcp_bxorfalse_nodelay b, mask
389-
mcrr2 p7, #5, \b , \mask , c8
390-
.endm
391-
392-
// Assert (x ^ parity) == 0x96009600u
393-
.macro rcp_ivalid x, parity
394-
mcrr p7, #6, \x , \parity , c8
395-
.endm
396-
397-
.macro rcp_ivalid_nodelay x, parity
398-
mcrr2 p7, #6, \x , \parity , c8
399-
.endm
400-
401-
// Assert x == y
402-
.macro rcp_iequal x, y
403-
mcrr p7, #7, \x , \y , c0
404-
.endm
405-
406-
.macro rcp_iequal_nodelay x, y
407-
mcrr2 p7, #7, \x , \y , c0
408-
.endm
409-
410-
// They call this "metaprogramming" I think
320+
// Meta-macro for evaluating assembler constant expressions and encoding as
321+
// coprocessor register pairs:
411322
.macro rcp_switch_u8_to_ch_cl macro_name, x, args:vararg
412323
.if (\x) == 0
413324
\macro_name c0, c0, \args
@@ -926,6 +837,114 @@ static __rcpinline __attribute__((noreturn)) void rcp_panic(void) {
926837
.endif
927838
.endm
928839

840+
// ----------------------------------------------------------------------------
841+
// RCP Boolean instructions
842+
843+
// Assert b is a valid boolean (0xa500a500u or 0x00c300c3u)
844+
.macro rcp_bvalid r
845+
mcr p7, #1, \r , c0, c0, #0
846+
.endm
847+
848+
.macro rcp_bvalid_nodelay r
849+
mcr2 p7, #1, \r , c0, c0, #0
850+
.endm
851+
852+
// Assert b is true (0xa500a500u)
853+
.macro rcp_btrue r
854+
mcr p7, #2, \r , c0, c0, #0
855+
.endm
856+
857+
.macro rcp_btrue_nodelay r
858+
mcr2 p7, #2, \r , c0, c0, #0
859+
.endm
860+
861+
// Assert b is false (0x00c300c3u)
862+
.macro rcp_bfalse r
863+
mcr p7, #3, \r , c0, c0, #1
864+
.endm
865+
866+
.macro rcp_bfalse_nodelay r
867+
mcr2 p7, #3, \r , c0, c0, #1
868+
.endm
869+
870+
// Assert b0 and b1 are both valid booleans
871+
.macro rcp_b2valid b0, b1
872+
mcrr p7, #0, \b0 , \b1 , c8
873+
.endm
874+
875+
.macro rcp_b2valid_nodelay b0, b1
876+
mcrr2 p7, #0, \b0 , \b1 , c8
877+
.endm
878+
879+
// Assert b0 and b1 are both true
880+
.macro rcp_b2and b0, b1
881+
mcrr p7, #1, \b0 , \b1 , c0
882+
.endm
883+
884+
.macro rcp_b2and_nodelay b0, b1
885+
mcrr2 p7, #1, \b0 , \b1 , c0
886+
.endm
887+
888+
// Assert b0 and b1 are valid, and at least one is true
889+
.macro rcp_b2or b0, b1
890+
mcrr p7, #2, \b0 , \b1 , c0
891+
.endm
892+
893+
.macro rcp_b2or_nodelay b0, b1
894+
mcrr2 p7, #2, \b0 , \b1 , c0
895+
.endm
896+
897+
// Assert (b ^ mask) is a valid boolean
898+
.macro rcp_bxorvalid b, mask
899+
mcrr p7, #3, \b , \mask , c8
900+
.endm
901+
902+
.macro rcp_bxorvalid_nodelay b, mask
903+
mcrr2 p7, #3, \b , \mask , c8
904+
.endm
905+
906+
// Assert (b ^ mask) is true
907+
.macro rcp_bxortrue b, mask
908+
mcrr p7, #4, \b , \mask , c0
909+
.endm
910+
911+
.macro rcp_bxortrue_nodelay b, mask
912+
mcrr2 p7, #4, \b , \mask , c0
913+
.endm
914+
915+
// Assert (b ^ mask) is false
916+
.macro rcp_bxorfalse b, mask
917+
mcrr p7, #5, \b , \mask , c8
918+
.endm
919+
920+
.macro rcp_bxorfalse_nodelay b, mask
921+
mcrr2 p7, #5, \b , \mask , c8
922+
.endm
923+
924+
// ----------------------------------------------------------------------------
925+
// RCP Integer instructions
926+
927+
// Assert (x ^ parity) == 0x96009600u
928+
.macro rcp_ivalid x, parity
929+
mcrr p7, #6, \x , \parity , c8
930+
.endm
931+
932+
.macro rcp_ivalid_nodelay x, parity
933+
mcrr2 p7, #6, \x , \parity , c8
934+
.endm
935+
936+
// Assert x == y
937+
.macro rcp_iequal x, y
938+
mcrr p7, #7, \x , \y , c0
939+
.endm
940+
941+
.macro rcp_iequal_nodelay x, y
942+
mcrr2 p7, #7, \x , \y , c0
943+
.endm
944+
945+
// ----------------------------------------------------------------------------
946+
// RCP Sequence count instructions
947+
929948
// Directly write 8-bit constant expression cnt to the sequence counter.
930949
.macro rcp_count_set_impl h, l
931950
mcr p7, #4, r0, \h , \l , #0
@@ -957,20 +976,20 @@ rcp_switch_u8_to_ch_cl rcp_count_check_impl, \cnt
957976
rcp_switch_u8_to_ch_cl rcp_count_check_nodelay_impl, \cnt
958977
.endm
959978

979+
// ----------------------------------------------------------------------------
980+
// RCP Canary instructions
981+
960982
// Get a 32-bit canary value. `tag` must be a constant expression.
961983
.macro rcp_canary_get_impl h, l, x
962984
mrc p7, #0, \x, \h, \l, #1
963985
.endm
964-
965986
.macro rcp_canary_get x, tag
966987
rcp_switch_u8_to_ch_cl rcp_canary_get_impl \tag, \x
967988
.endm
968989

969-
// Get a 32-bit canary value. `tag` must be a constant expression.
970990
.macro rcp_canary_get_nodelay_impl h, l, x
971991
mrc2 p7, #0, \x, \h, \l, #1
972992
.endm
973-
974993
.macro rcp_canary_get_nodelay x, tag
975994
rcp_switch_u8_to_ch_cl rcp_canary_get_nodelay_impl \tag, \x
976995
.endm
@@ -979,15 +998,13 @@ rcp_switch_u8_to_ch_cl rcp_canary_get_nodelay_impl \tag, \x
979998
.macro rcp_canary_check_impl h, l, x
980999
mcr p7, #0, \x, \h, \l, #1
9811000
.endm
982-
9831001
.macro rcp_canary_check x, tag
9841002
rcp_switch_u8_to_ch_cl rcp_canary_check_impl \tag, \x
9851003
.endm
9861004

9871005
.macro rcp_canary_check_nodelay_impl h, l, x
9881006
mcr2 p7, #0, \x, \h, \l, #1
9891007
.endm
990-
9911008
.macro rcp_canary_check_nodelay x, tag
9921009
rcp_switch_u8_to_ch_cl rcp_canary_check_nodelay_impl \tag, \x
9931010
.endm
@@ -996,13 +1013,14 @@ rcp_switch_u8_to_ch_cl rcp_canary_check_nodelay_impl \tag, \x
9961013
cdp p7, #0, c0, c0, c0, #1
9971014
.endm
9981015

999-
#endif // HAS_REDUNDANCY_COPROCESSOR
1000-
#endif // !PICO_RP2040
1016+
#endif // !__riscv
10011017
#endif // __ASSEMBLER__
10021018
// ----------------------------------------------------------------------------
10031019

10041020
#ifdef __cplusplus
10051021
}
10061022
#endif
1023+
#else
1024+
#define rcp_is_true(x) ((int32_t)(x) < 0)
10071025
#endif
10081026
#endif

src/rp2_common/pico_bootrom/bootrom.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ int rom_pick_ab_update_partition(uint32_t *workarea_base, uint32_t workarea_size
160160

161161
int rc = rom_pick_ab_partition((uint8_t*)workarea_base, workarea_size, partition_a_num, flash_update_base);
162162

163-
if (IMAGE_DEF_VERIFIED(workarea_base) != RCP_MASK_TRUE) {
163+
if (!rcp_is_true(IMAGE_DEF_VERIFIED(workarea_base))) {
164164
// Chosen partition failed verification
165165
return BOOTROM_ERROR_NOT_FOUND;
166166
}

0 commit comments

Comments
 (0)