hc
2024-08-12 233ab1bd4c5697f5cdec94e60206e8c6ac609b4c
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
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
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
/*
 * Copyright (C) 2010 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
 
/**
 * RecoverySystem contains methods for interacting with the Android
 * recovery system (the separate partition that can be used to install
 * system updates, wipe user data, etc.)
 */
 
//#include <direct.h>
#include <linux/reboot.h>
//#include <io.h>
#include <stdio.h>
#include <string.h>
#include <sys/reboot.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
 
#include "update_recv/update_recv.h"
 
#define LOG_FILE_LEN 512
 
#if 0
#define RECOVERY_PATH "/tmp/recovery"
#define LOG_FILE_PATH "/tmp/recovery/log"
#define COMMAND_FILE_PATH "/tmp/recovery/command"
#else
#define RECOVERY_PATH "/userdata/recovery"
#define LOG_FILE_PATH "/userdata/recovery/log"
#define COMMAND_FILE_PATH "/userdata/recovery/command"
#endif
 
#define SD_UPDATE_FILE "/sdcard/update.img"
#define DATA_UPDATE_FILE "/userdata/update.img"
#define MISC_FILE_PATH "/dev/block/by-name/misc"
#define MISC_MSG_OFFSET 16 * 1024
 
/* Bootloader Message (2-KiB)
 *
 * This structure describes the content of a block in flash
 * that is used for recovery and the bootloader to talk to
 * each other.
 *
 * The command field is updated by linux when it wants to
 * reboot into recovery or to update radio or bootloader firmware.
 * It is also updated by the bootloader when firmware update
 * is complete (to boot into recovery for any final cleanup)
 *
 * The status field is written by the bootloader after the
 * completion of an "update-radio" or "update-hboot" command.
 *
 * The recovery field is only written by linux and used
 * for the system to send a message to recovery or the
 * other way around.
 *
 * The stage field is written by packages which restart themselves
 * multiple times, so that the UI can reflect which invocation of the
 * package it is.  If the value is of the format "#/#" (eg, "1/3"),
 * the UI will add a simple indicator of that status.
 *
 * We used to have slot_suffix field for A/B boot control metadata in
 * this struct, which gets unintentionally cleared by recovery or
 * uncrypt. Move it into struct bootloader_message_ab to avoid the
 * issue.
 */
struct android_bootloader_message {
   char command[32];
   char status[32];
   char recovery[768];
 
   /* The 'recovery' field used to be 1024 bytes.    It has only ever
    * been used to store the recovery command line, so 768 bytes
    * should be plenty.  We carve off the last 256 bytes to store the
    * stage string (for multistage packages) and possible future
    * expansion. */
   char stage[32];
 
   /* The 'reserved' field used to be 224 bytes when it was initially
    * carved off from the 1024-byte recovery field. Bump it up to
    * 1184-byte so that the entire bootloader_message struct rounds up
    * to 2048-byte. */
   char reserved[1184];
};
 
 
 
/**
 * Reboot into the recovery system with the supplied argument.
 * @param arg to pass to the recovery utility.
 */
static void bootCommand(char *arg){
   FILE *command_file;
   FILE *log_file;
   FILE *misc_file;
   char blank[LOG_FILE_LEN];
 
   if(!arg) return;
   printf("command: %s\n", arg);
   mkdir(RECOVERY_PATH,0775);
   if((command_file = fopen(COMMAND_FILE_PATH,"wb")) == NULL){
       printf("Open command file error.\n");
       return;
   }
 
   if((log_file = fopen(LOG_FILE_PATH,"wb")) == NULL){
       printf("Open log file error.\n");
       return;
   }
 
   if((misc_file = fopen(MISC_FILE_PATH,"wb")) == NULL){
       printf("Open misc file error.\n");
       return;
   }
 
   printf("update: write command to command file: ");
   fwrite(arg, strlen(arg), 1, command_file);
   fwrite("\n", 1, 1, command_file);
   fclose(command_file);
   printf("done\n");
 
   printf("update: write command to misc file: ");
   fseek(misc_file, MISC_MSG_OFFSET, SEEK_SET);
   struct android_bootloader_message msg;
   memset(&msg, 0, sizeof(msg));
   char recovery_str[] = "recovery\n";
   strcpy(msg.command, "boot-recovery");
   strcpy(msg.recovery, recovery_str);
   memcpy(msg.recovery + strlen(recovery_str), arg, ((strlen(arg) > sizeof(msg.recovery))? sizeof(msg.recovery) : strlen(arg)));
   msg.recovery[strlen(msg.recovery) + 1] = '\n';
   //strlcat(msg.recovery, update_file, sizeof(msg.recovery));
   //strlcat(msg.recovery, "\n", sizeof(msg.recovery));
   //strlcpy(msg.systemFlag, "false", sizeof(msg.systemFlag));
   fwrite(&msg, sizeof(msg), 1, misc_file);
   fclose(misc_file);
   printf("done\n");
 
   memset(blank, 0, LOG_FILE_LEN);
   fwrite(blank, LOG_FILE_LEN, 1, log_file);
   fclose(log_file);
   printf("update: reboot!\n");
   //reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2,
   //         LINUX_REBOOT_CMD_RESTART2, "recovery");
   sync();
   reboot(RB_AUTOBOOT);
   return;
}
 
 
 /**
 * Reboots the device in order to install the given update
 * package.
 * Requires the {@link android.Manifest.permission#REBOOT} permission.
 *
 * @param packageFile  the update package to install.  Must be on
 * a partition mountable by recovery.  (The set of partitions
 * known to recovery may vary from device to device.  Generally,
 * /cache and /data are safe.)
 */
static void installPackage(char *update_file){
   char arg[512];
   char *str_update_package = "--update_package=";
   int str_update_package_len = strlen(str_update_package);
   int str_update_file_len = strlen(update_file);
 
   memset(arg, 0, 512);
   strcpy(arg, str_update_package);
   strcpy(arg + str_update_package_len, update_file);
   arg[str_update_package_len + str_update_file_len] = 0;
   bootCommand(arg);
}
 
static void sdUpdate(){
   installPackage(SD_UPDATE_FILE);
}
 
static void dataUpdate(){
   installPackage(DATA_UPDATE_FILE);
}
 
/**
 * Reboots the device and wipes the user data partition.  This is
 * sometimes called a "factory reset", which is something of a
 * misnomer because the system partition is not restored to its
 * factory state.
 * Requires the {@link android.Manifest.permission#REBOOT} permission.
 *
 * @param context  the Context to use
 *
 */
void rebootWipeUserData(){
   printf("update: --wipe_all\n");
   bootCommand("--wipe_all");
}
 
int rebootUpdate(char *path){
 
   if(path){
       printf("find %s\n", path);
       installPackage(path);
       return 0;
   }
 
   if(access(DATA_UPDATE_FILE,F_OK) == -1){
       printf("%s does not exist! try to use %s to update\n",
           DATA_UPDATE_FILE, SD_UPDATE_FILE);
       if(access(SD_UPDATE_FILE,F_OK) == -1){
           printf("%s does not exist!\n", SD_UPDATE_FILE);
           return -1;
       }
       printf("find %s\n", SD_UPDATE_FILE);
       installPackage(SD_UPDATE_FILE);
       return 0;
   }
 
   printf("find %s\n", DATA_UPDATE_FILE);
   installPackage(DATA_UPDATE_FILE);
   return 0;
}
 
int main(int argc, char** argv){
   char* partition_name = "recovery";
   printf("update: Rockchip Update Tool\n");
 
   if(argc == 1) {
       rebootWipeUserData();
   } else if(argc == 2){
       if(!strcmp(argv[1], "ota") || !strcmp(argv[1], "update"))
           rebootUpdate(0);
       else if(!strcmp(argv[1], "factory") || !strcmp(argv[1], "reset"))
           rebootWipeUserData();
       else  return -1;
 
       return 0;
 
   } else if(argc == 3){
       if(!strcmp(argv[1], "ota") || !strcmp(argv[1], "update")) {
           if(argv[2]) {
               int ret;
               ret = WriteFwData(argv[2], partition_name);
               if (ret < 0) {
                   if (ret == -1) {
                       printf(" Update partition %s fail \n", partition_name);
                       //means no find recovery partition in update.img
                       //return -1;
                   } else if (ret == -2) {
                       printf("Some errors happen, update process break...\n");
                       return -1;
                   }
               } else {
                   if (!CheckFwData(argv[2], partition_name)){
                       printf(" Check partition %s fail \n", partition_name);
                       return -1;
                   }
               }
               return rebootUpdate(argv[2]);
           }
       }
   }
 
   return -1;
}