SingingCat 0
application
partitions.c
1#include "partitions.h"
2#include "flashapp.h"
3
4extern uint32_t app_base;
5
6// return 0 if valid
7static int check_partition(struct partition *p) {
8 if (p->magic != PART_MAGIC) {
9 printf("Partition at %p has invalid magic\r\n", p);
10 return 1;
11 }
12 if (p->layout_version != 1) {
13 printf("Partition at %p has invalid layout_version %i\r\n", p, p->layout_version);
14 return 2;
15 }
16 uint32_t crc = calc_crc32((void *)p, sizeof(struct partition), 4);
17
18 if (crc != p->crc) {
19 printf("Partition at %p has invalid checksum. Stored=%i,Calc=%i\r\n", p, p->crc, crc);
20 return 3;
21 }
22 printf("Partition at %p is valid (sequence %i)\r\n", p, p->part_seq);
23 return 0;
24}
25
26// if partitions exit, do nothing, otherwise create one partition and make this app default in that partition
27void partition_init() {
28 int i = check_partition((void *)PARTITION_BASE);
29
30 if (i == 0) {
31 return;
32 }
33 i = check_partition((void *)PARTITION_BASE + 1024);
34 if (i == 0) {
35 return;
36 }
37 printf("Creating partition...\r\n");
38 uint8_t buf[1024];
39
40 memset(buf, 0, 1024);
41 struct partition *np = (void *)&buf;
42
43 np->magic = PART_MAGIC;
44 np->layout_version = 1;
45 np->part_seq = 1;
46 struct appdef *ap = &np->appdefs;
47
48 ap->size = sizeof(struct appdef);
49 ap->app_header = (uint32_t)&app_base; // my base address, defined in linker script
50 ap->app_seq = 1;
51 // endmarker
52 ap = ap + ap->size;
53 ap->size = 0;
54
55 // finally, calc checksum
56 np->crc = calc_crc32(buf, 1024, 4);
57 // create partitions...
58 printf("Writing partition to flash...\r\n");
59 flash_write((void *)&buf, (void *)PARTITION_BASE, 1024);
60}
61static struct partition *get_active_partition() {
62 struct partition *p1 = (void *)PARTITION_BASE;
63 struct partition *p2 = (void *)PARTITION_BASE + 1024;
64 int v1 = check_partition(p1); // 00=valid
65 int v2 = check_partition(p2); // 00=vaild
66
67 if ((v1 != 0) && (v2 != 0)) {
68 // neither is valid
69 return NULL;
70 }
71 // at least one is valid
72
73 // if one is invalid, return the other one
74 if (v1 != 0) {
75 return p2;
76 }
77 if (v2 != 0) {
78 return p1;
79 }
80
81 //both are valid
82 if (p2->part_seq > p1->part_seq) {
83 return p2;
84 }
85 return p1;
86}
87
88static struct partition *get_next_partition_to_write() {
89 void *x = get_active_partition();
90
91 if (x == NULL) {
92 return (void *)PARTITION_BASE;
93 }
94 if (x == (void *)PARTITION_BASE) {
95 return (void *)PARTITION_BASE + 1024;
96 }
97 return (void *)PARTITION_BASE;
98}
99
100// set the base to be the next app to boot in the partition table
101void partition_set_latest_app(void *base) {
102 struct partition *pw = get_next_partition_to_write();
103 struct partition *pa = get_active_partition();
104
105 printf("Active partition: 0x%p\r\n", pa);
106 printf("Write partition: 0x%p\r\n", pw);
107 uint8_t buf[1024];
108
109 memset(buf, 0, 1024);
110 // copy active partition to new one to write
111 if (pa != NULL) {
112 int i;
113 uint8_t *source = (void *)pa;
114 for (i = 0; i < 1024; i++) {
115 buf[i] = source[i];
116 }
117 }
118 struct partition *np = (void *)&buf;
119
120 np->magic = PART_MAGIC;
121 np->layout_version = 1;
122 np->part_seq++;
123 struct appdef *ap = &np->appdefs;
124
125 ap->size = sizeof(struct appdef);
126 ap->app_header = (uint32_t)base;
127 ap->app_seq = 1;
128 // endmarker
129 ap = ap + ap->size;
130 ap->size = 0;
131
132 // finally, calc checksum
133 np->crc = calc_crc32(buf, 1024, 4);
134 // create partitions...
135 printf("Writing partition @%p to flash...\r\n", pw);
136 flash_write((void *)&buf, (void *)pw, 1024);
137}
int flash_write(byte *b, void *adr, int size)
unlock, erase, write, lock
Definition: flashapp.c:157