xref: /OK3568_Linux_fs/external/rktoolkit/update.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /*
2  * Copyright (C) 2010 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *    http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 /**
18  * RecoverySystem contains methods for interacting with the Android
19  * recovery system (the separate partition that can be used to install
20  * system updates, wipe user data, etc.)
21  */
22 
23 //#include <direct.h>
24 #include <linux/reboot.h>
25 //#include <io.h>
26 #include <stdio.h>
27 #include <string.h>
28 #include <sys/reboot.h>
29 #include <sys/stat.h>
30 #include <sys/types.h>
31 #include <unistd.h>
32 
33 #include "update_recv/update_recv.h"
34 
35 #define LOG_FILE_LEN 512
36 
37 #if 0
38 #define RECOVERY_PATH "/tmp/recovery"
39 #define LOG_FILE_PATH "/tmp/recovery/log"
40 #define COMMAND_FILE_PATH "/tmp/recovery/command"
41 #else
42 #define RECOVERY_PATH "/userdata/recovery"
43 #define LOG_FILE_PATH "/userdata/recovery/log"
44 #define COMMAND_FILE_PATH "/userdata/recovery/command"
45 #endif
46 
47 #define SD_UPDATE_FILE "/sdcard/update.img"
48 #define DATA_UPDATE_FILE "/userdata/update.img"
49 #define MISC_FILE_PATH "/dev/block/by-name/misc"
50 #define MISC_MSG_OFFSET 16 * 1024
51 
52 /* Bootloader Message (2-KiB)
53  *
54  * This structure describes the content of a block in flash
55  * that is used for recovery and the bootloader to talk to
56  * each other.
57  *
58  * The command field is updated by linux when it wants to
59  * reboot into recovery or to update radio or bootloader firmware.
60  * It is also updated by the bootloader when firmware update
61  * is complete (to boot into recovery for any final cleanup)
62  *
63  * The status field is written by the bootloader after the
64  * completion of an "update-radio" or "update-hboot" command.
65  *
66  * The recovery field is only written by linux and used
67  * for the system to send a message to recovery or the
68  * other way around.
69  *
70  * The stage field is written by packages which restart themselves
71  * multiple times, so that the UI can reflect which invocation of the
72  * package it is.  If the value is of the format "#/#" (eg, "1/3"),
73  * the UI will add a simple indicator of that status.
74  *
75  * We used to have slot_suffix field for A/B boot control metadata in
76  * this struct, which gets unintentionally cleared by recovery or
77  * uncrypt. Move it into struct bootloader_message_ab to avoid the
78  * issue.
79  */
80 struct android_bootloader_message {
81 	char command[32];
82 	char status[32];
83 	char recovery[768];
84 
85 	/* The 'recovery' field used to be 1024 bytes.	It has only ever
86 	 * been used to store the recovery command line, so 768 bytes
87 	 * should be plenty.  We carve off the last 256 bytes to store the
88 	 * stage string (for multistage packages) and possible future
89 	 * expansion. */
90 	char stage[32];
91 
92 	/* The 'reserved' field used to be 224 bytes when it was initially
93 	 * carved off from the 1024-byte recovery field. Bump it up to
94 	 * 1184-byte so that the entire bootloader_message struct rounds up
95 	 * to 2048-byte. */
96 	char reserved[1184];
97 };
98 
99 
100 
101 /**
102  * Reboot into the recovery system with the supplied argument.
103  * @param arg to pass to the recovery utility.
104  */
bootCommand(char * arg)105 static void bootCommand(char *arg){
106 	FILE *command_file;
107 	FILE *log_file;
108 	FILE *misc_file;
109 	char blank[LOG_FILE_LEN];
110 
111 	if(!arg) return;
112 	printf("command: %s\n", arg);
113 	mkdir(RECOVERY_PATH,0775);
114 	if((command_file = fopen(COMMAND_FILE_PATH,"wb")) == NULL){
115 		printf("Open command file error.\n");
116 		return;
117 	}
118 
119 	if((log_file = fopen(LOG_FILE_PATH,"wb")) == NULL){
120 		printf("Open log file error.\n");
121 		return;
122 	}
123 
124 	if((misc_file = fopen(MISC_FILE_PATH,"wb")) == NULL){
125 		printf("Open misc file error.\n");
126 		return;
127 	}
128 
129 	printf("update: write command to command file: ");
130 	fwrite(arg, strlen(arg), 1, command_file);
131 	fwrite("\n", 1, 1, command_file);
132 	fclose(command_file);
133 	printf("done\n");
134 
135 	printf("update: write command to misc file: ");
136 	fseek(misc_file, MISC_MSG_OFFSET, SEEK_SET);
137 	struct android_bootloader_message msg;
138 	memset(&msg, 0, sizeof(msg));
139 	char recovery_str[] = "recovery\n";
140 	strcpy(msg.command, "boot-recovery");
141 	strcpy(msg.recovery, recovery_str);
142 	memcpy(msg.recovery + strlen(recovery_str), arg, ((strlen(arg) > sizeof(msg.recovery))? sizeof(msg.recovery) : strlen(arg)));
143 	msg.recovery[strlen(msg.recovery) + 1] = '\n';
144 	//strlcat(msg.recovery, update_file, sizeof(msg.recovery));
145 	//strlcat(msg.recovery, "\n", sizeof(msg.recovery));
146 	//strlcpy(msg.systemFlag, "false", sizeof(msg.systemFlag));
147 	fwrite(&msg, sizeof(msg), 1, misc_file);
148 	fclose(misc_file);
149 	printf("done\n");
150 
151 	memset(blank, 0, LOG_FILE_LEN);
152 	fwrite(blank, LOG_FILE_LEN, 1, log_file);
153 	fclose(log_file);
154 	printf("update: reboot!\n");
155 	//reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2,
156 	//		 LINUX_REBOOT_CMD_RESTART2, "recovery");
157 	sync();
158 	reboot(RB_AUTOBOOT);
159 	return;
160 }
161 
162 
163  /**
164  * Reboots the device in order to install the given update
165  * package.
166  * Requires the {@link android.Manifest.permission#REBOOT} permission.
167  *
168  * @param packageFile  the update package to install.  Must be on
169  * a partition mountable by recovery.  (The set of partitions
170  * known to recovery may vary from device to device.  Generally,
171  * /cache and /data are safe.)
172  */
installPackage(char * update_file)173 static void installPackage(char *update_file){
174 	char arg[512];
175 	char *str_update_package = "--update_package=";
176 	int str_update_package_len = strlen(str_update_package);
177 	int str_update_file_len = strlen(update_file);
178 
179 	memset(arg, 0, 512);
180 	strcpy(arg, str_update_package);
181 	strcpy(arg + str_update_package_len, update_file);
182 	arg[str_update_package_len + str_update_file_len] = 0;
183 	bootCommand(arg);
184 }
185 
sdUpdate()186 static void sdUpdate(){
187 	installPackage(SD_UPDATE_FILE);
188 }
189 
dataUpdate()190 static void dataUpdate(){
191 	installPackage(DATA_UPDATE_FILE);
192 }
193 
194 /**
195  * Reboots the device and wipes the user data partition.  This is
196  * sometimes called a "factory reset", which is something of a
197  * misnomer because the system partition is not restored to its
198  * factory state.
199  * Requires the {@link android.Manifest.permission#REBOOT} permission.
200  *
201  * @param context  the Context to use
202  *
203  */
rebootWipeUserData()204 void rebootWipeUserData(){
205 	printf("update: --wipe_all\n");
206 	bootCommand("--wipe_all");
207 }
208 
rebootUpdate(char * path)209 int rebootUpdate(char *path){
210 
211 	if(path){
212 		printf("find %s\n", path);
213 		installPackage(path);
214 		return 0;
215 	}
216 
217 	if(access(DATA_UPDATE_FILE,F_OK) == -1){
218 		printf("%s does not exist! try to use %s to update\n",
219 			DATA_UPDATE_FILE, SD_UPDATE_FILE);
220 		if(access(SD_UPDATE_FILE,F_OK) == -1){
221 			printf("%s does not exist!\n", SD_UPDATE_FILE);
222 			return -1;
223 		}
224 		printf("find %s\n", SD_UPDATE_FILE);
225 		installPackage(SD_UPDATE_FILE);
226 		return 0;
227 	}
228 
229 	printf("find %s\n", DATA_UPDATE_FILE);
230 	installPackage(DATA_UPDATE_FILE);
231 	return 0;
232 }
233 
main(int argc,char ** argv)234 int main(int argc, char** argv){
235 	char* partition_name = "recovery";
236 	printf("update: Rockchip Update Tool\n");
237 
238 	if(argc == 1) {
239 		rebootWipeUserData();
240 	} else if(argc == 2){
241 		if(!strcmp(argv[1], "ota") || !strcmp(argv[1], "update"))
242 			rebootUpdate(0);
243 		else if(!strcmp(argv[1], "factory") || !strcmp(argv[1], "reset"))
244 			rebootWipeUserData();
245 		else  return -1;
246 
247 		return 0;
248 
249 	} else if(argc == 3){
250 		if(!strcmp(argv[1], "ota") || !strcmp(argv[1], "update")) {
251 			if(argv[2]) {
252 				int ret;
253 				ret = WriteFwData(argv[2], partition_name);
254 				if (ret < 0) {
255 					if (ret == -1) {
256 						printf(" Update partition %s fail \n", partition_name);
257 						//means no find recovery partition in update.img
258 						//return -1;
259 					} else if (ret == -2) {
260 						printf("Some errors happen, update process break...\n");
261 						return -1;
262 					}
263 				} else {
264 					if (!CheckFwData(argv[2], partition_name)){
265 						printf(" Check partition %s fail \n", partition_name);
266 						return -1;
267 					}
268 				}
269 				return rebootUpdate(argv[2]);
270 			}
271 		}
272 	}
273 
274 	return -1;
275 }
276 
277