forked from zackxue/ipc
-
Notifications
You must be signed in to change notification settings - Fork 11
/
Copy pathfirmware_upgrade.c
161 lines (131 loc) · 3.49 KB
/
firmware_upgrade.c
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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
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
158
159
#include "firmware.h"
#define FIRMWARE_UPGRADE_SPEED (128 * 1024)
typedef struct FwUpgrade
{
ssize_t upgrade_size;
ssize_t total_size;
pthread_t upgrade_tid;
uint32_t upgrade_trigger;
}FwUpgrade_t;
static FwUpgrade_t* _fw_upgrade = NULL;
int FIRMWARE_upgrade_get_rate()
{
if(0 == _fw_upgrade->upgrade_size){
return 0;
}
return _fw_upgrade->upgrade_size * 100 / _fw_upgrade->total_size;
}
static int firmware_upgrade_flash(int flash_fd, off_t flash_offset, int fw_fd, off_t fw_offset, ssize_t data_size)
{
int ret = 0;
uint8_t buf[FIRMWARE_UPGRADE_SPEED];
assert(flash_fd > 0 && fw_fd > 0);
ret = lseek(fw_fd, fw_offset, SEEK_SET);
assert(fw_offset == ret);
ret = lseek(flash_fd, flash_offset, SEEK_SET);
assert(flash_offset == ret);
do
{
ssize_t read_sz = data_size >= FIRMWARE_UPGRADE_SPEED ? FIRMWARE_UPGRADE_SPEED : data_size;
// read from firmware
ret = read(fw_fd, buf, read_sz);
assert(ret == read_sz);
// write to flash
ret = write(flash_fd, buf, read_sz);
assert(ret == read_sz);
// fdatasync(flash_fd);
fsync(flash_fd);
data_size -= read_sz;
_fw_upgrade->upgrade_size += read_sz;
}while(data_size > 0);
return 0;
}
static void* firmware_upgrade(void* arg)
{
printf("%s start\n", __FUNCTION__);
int i = 0;
int ret = 0;
FwHeader_t fw_header;
int fid = -1;
// // detach thread
// pthread_detach(pthread_self());
fid = open(FIRMWARE_IMPORT_FILE, O_RDONLY);
assert(fid > 0);
ret = read(fid, &fw_header, sizeof(fw_header));
assert(sizeof(fw_header) == ret);
// FIRMWARE_dump_rom(FIRMWARE_IMPORT_FILE);
// get total size to upgrade
_fw_upgrade->total_size = 0;
_fw_upgrade->upgrade_size = 0;
for(i = 0; i < fw_header.block_cnt; ++i){
_fw_upgrade->total_size += fw_header.block[i].data_size;
}
// printf("upgrade total size = %d\r\n", _fw_upgrade->total_size);
// upgrade
for(i = 0; i < fw_header.block_cnt && _fw_upgrade->upgrade_trigger; ++i){
int flash_fd = open(fw_header.block[i].flash, O_RDWR);
// printf("upgrade %s offset=%d size = %d\r\n", fw_header.block[i].flash, fw_header.block[i].data_offset, fw_header.block[i].data_size);
if(flash_fd > 0){
firmware_upgrade_flash(flash_fd, fw_header.block[i].flash_offset, fid, fw_header.block[i].data_offset, fw_header.block[i].data_size);
close(flash_fd);
flash_fd = -1;
}
}
close(fid);
printf("%s end\n", __FUNCTION__);
system("reboot"); // must reboot
pthread_exit(NULL);
}
int FIRMWARE_upgrade_start()
{
printf("%s start\n", __FUNCTION__);
if(!_fw_upgrade->upgrade_tid){
int ret = 0;
if(FIRMWARE_import_check()){
// import file check ok!!
_fw_upgrade->upgrade_trigger = true;
ret = pthread_create(&_fw_upgrade->upgrade_tid, NULL, firmware_upgrade, NULL);
assert(0 == ret);
return 0;
}
}
return -1;
}
int FIRMWARE_upgrade_wait()
{
if(_fw_upgrade->upgrade_tid){
pthread_join(_fw_upgrade->upgrade_tid, NULL);
_fw_upgrade->upgrade_trigger = false;
_fw_upgrade->upgrade_tid = (pthread_t)NULL;
return 0;
}
return -1;
}
int FIRMWARE_upgrade_cancel()
{
if(_fw_upgrade->upgrade_tid){
_fw_upgrade->upgrade_trigger = false;
return FIRMWARE_upgrade_wait();
}
return -1;
}
int FIRMWARE_upgrade_init()
{
if(!_fw_upgrade){
_fw_upgrade = calloc(sizeof(FwUpgrade_t), 1);
_fw_upgrade->upgrade_size = 0;
_fw_upgrade->total_size = 0;
_fw_upgrade->upgrade_tid = (pthread_t)NULL;
_fw_upgrade->upgrade_trigger = false;
return 0;
}
return -1;
}
void FIRMWARE_upgrade_destroy()
{
if(_fw_upgrade){
FIRMWARE_upgrade_cancel();
free(_fw_upgrade);
_fw_upgrade = NULL;
}
}