关于fastboot的使用方法,可以看看(/system/core/fastboot/fastboot.cpp)fastboot.cpp中的usage方法,里面讲的很详细.如果你用过fastboot 您才能知道我下文讲的是是什么。
首先看Android.mk,可以fastboot用的源文件protocol.c engine.c bootimg_utils.cpp fastboot.cpp util.c fs.c
这些源文件和lib会被build一个fastboot 的可执行bin档(include $(BUILD_HOST_EXECUTABLE)).
xref: /system/core/fastboot/Android.mk
1LOCAL_C_INCLUDES := $(LOCAL_PATH)/../mkbootimg \
22 $(LOCAL_PATH)/../../extras/ext4_utils \
23 $(LOCAL_PATH)/../../extras/f2fs_utils
24LOCAL_SRC_FILES := protocol.c engine.c bootimg_utils.cpp fastboot.cpp util.c fs.c
25LOCAL_MODULE := fastboot
26LOCAL_MODULE_TAGS := debug
27LOCAL_CONLYFLAGS += -std=gnu99
28LOCAL_CFLAGS += -Wall -Wextra -Werror -Wunreachable-code
由下面这段可以fastboot 可以support的host为linux/darwin/window.
32ifeq ($(HOST_OS),linux)
33 LOCAL_SRC_FILES += usb_linux.c util_linux.c
34endif
35
36ifeq ($(HOST_OS),darwin)
37 LOCAL_SRC_FILES += usb_osx.c util_osx.c
38 LOCAL_LDLIBS += -lpthread -framework CoreFoundation -framework IOKit -framework Carbon
39 LOCAL_CFLAGS += -Wno-unused-parameter
40endif
41
42ifeq ($(HOST_OS),windows)
43 LOCAL_SRC_FILES += usb_windows.c util_windows.c
有43行可以usb_windows.c util_windows.c 是用于通过usb 给板子发送命令的.
既然fastboot 是一个可以执行的bin,那我们来看看其main函数的实现。
xref: /system/core/fastboot/fastboot.cpp
int main(int argc, char **argv)
1006{
1114
1115 if (argc > 0 && !strcmp(*argv, "devices")) {
1116 skip(1);
1117 list_devices();
1118 return 0;
1119 }
1120
1121 if (argc > 0 && !strcmp(*argv, "help")) {
1122 usage();
1123 return 0;
1124 }
1125
1126 usb_handle* usb = open_device();
1127
1128 while (argc > 0) {
1129 if(!strcmp(*argv, "getvar")) {
1130 require(2);
1131 fb_queue_display(argv[1], argv[1]);
1132 skip(2);
1133 } else if(!strcmp(*argv, "erase")) {
1134 require(2);
1135
1136 if (fb_format_supported(usb, argv[1], NULL)) {
1137 fprintf(stderr, "******** Did you mean to fastboot format this partition?\n");
1138 }
1139
1140 fb_queue_erase(argv[1]);
1141 skip(2);
1142 } else if(!strncmp(*argv, "format", strlen("format"))) {
1143 char *overrides;
1144 char *type_override = NULL;
1145 char *size_override = NULL;
1146 require(2);
1156 overrides = strchr(*argv, ':');
1157 if (overrides) {
1158 overrides++;
1159 size_override = strchr(overrides, ':');
1160 if (size_override) {
1161 size_override[0] = '\0';
1162 size_override++;
1163 }
1164 type_override = overrides;
1165 }
1166 if (type_override && !type_override[0]) type_override = NULL;
1167 if (size_override && !size_override[0]) size_override = NULL;
1168 if (erase_first && needs_erase(usb, argv[1])) {
1169 fb_queue_erase(argv[1]);
1170 }
1171 fb_perform_format(usb, argv[1], 0, type_override, size_override);
1172 skip(2);
1173 } else if(!strcmp(*argv, "signature")) {
1174 require(2);
1175 data = load_file(argv[1], &sz);
1176 if (data == 0) die("could not load '%s': %s", argv[1], strerror(errno));
1177 if (sz != 256) die("signature must be 256 bytes");
1178 fb_queue_download("signature", data, sz);
1179 fb_queue_command("signature", "installing signature");
1180 skip(2);
1181 } else if(!strcmp(*argv, "reboot")) {
1182 wants_reboot = 1;
1183 skip(1);
1184 if (argc > 0) {
1185 if (!strcmp(*argv, "bootloader")) {
1186 wants_reboot = 0;
1187 wants_reboot_bootloader = 1;
1188 skip(1);
1189 }
1190 }
1191 require(0);
1192 } else if(!strcmp(*argv, "reboot-bootloader")) {
1193 wants_reboot_bootloader = 1;
1194 skip(1);
1195 } else if (!strcmp(*argv, "continue")) {
1196 fb_queue_command("continue", "resuming boot");
1197 skip(1);
1198 } else if(!strcmp(*argv, "boot")) {
1199 char *kname = 0;
1200 char *rname = 0;
1201 skip(1);
1202 if (argc > 0) {
1203 kname = argv[0];
1204 skip(1);
1205 }
1206 if (argc > 0) {
1207 rname = argv[0];
1208 skip(1);
1209 }
1210 data = load_bootable_image(kname, rname, &sz, cmdline);
1211 if (data == 0) return 1;
1212 fb_queue_download("boot.img", data, sz);
1213 fb_queue_command("boot", "booting");
1214 } else if(!strcmp(*argv, "flash")) {
1215 char *pname = argv[1];
1216 char *fname = 0;
1217 require(2);
1218 if (argc > 2) {
1219 fname = argv[2];
1220 skip(3);
1221 } else {
1222 fname = find_item(pname, product);
1223 skip(2);
1224 }
1225 if (fname == 0) die("cannot determine image filename for '%s'", pname);
1226 if (erase_first && needs_erase(usb, pname)) {
1227 fb_queue_erase(pname);
1228 }
1229 do_flash(usb, pname, fname);
1294
1295 if (fb_queue_is_empty())
1296 return 0;
1297
1298 status = fb_execute_queue(usb);
1299 return (status) ? 1 : 0;
1300}
1126行是打开usb设备用于通讯,如我们所分析,因为我们用的host是window,所以实在usb_windows.c 实现.
H A D usb_windows.c 49 AdbWinApi.dll. This structure is returned from usb_open() routine and
376 usb_handle *usb_open(ifc_match_func callback) function
从1128行开始就是fastboot的命令。
我们以fastboot flash命令为例。
会执行1214行的flash命令。最终调用1229行的do_flash函数。
xref: /system/core/fastboot/fastboot.cpp
720void do_flash(usb_handle *usb, const char *pname, const char *fname)
721{
722 struct fastboot_buffer buf;
723
724 if (load_buf(usb, fname, &buf)) {
725 die("cannot load '%s'", fname);
726 }
727 flash_buf(pname, &buf);
728}
可见先调用724行的load_buf将数据读进来。下打开这个文件获取到fd,在根据fd来读文件.
687static int load_buf(usb_handle *usb, const char *fname,
688 struct fastboot_buffer *buf)
689{
690 int fd;
691
692 fd = open(fname, O_RDONLY | O_BINARY);
693 if (fd < 0) {
694 return -1;
695 }
696
697 return load_buf_fd(usb, fd, buf);
698}
其次调用来准备发送数据,可见支持FB_BUFFER_SPARSE 和 FB_BUFFER是(ext4 support的两种格式)
700static void flash_buf(const char *pname, struct fastboot_buffer *buf)
701{
702 sparse_file** s;
703
704 switch (buf->type) {
705 case FB_BUFFER_SPARSE:
706 s = reinterpret_cast<sparse_file**>(buf->data);
707 while (*s) {
708 int64_t sz64 = sparse_file_len(*s, true, false);
709 fb_queue_flash_sparse(pname, *s++, sz64);
710 }
711 break;
712 case FB_BUFFER:
713 fb_queue_flash(pname, buf->data, buf->sz);
714 break;
715 default:
716 die("unknown buffer type: %d", buf->type);
717 }
718}
我们以FB_BUFEER为例,调用fb_queue_flash(pname, buf->data, buf->sz); 来将要做的事情加入到列表中
175void fb_queue_flash(const char *ptn, void *data, unsigned sz)
176{
177 Action *a;
178
179 a = queue_action(OP_DOWNLOAD, "");
180 a->data = data;
181 a->size = sz;
182 a->msg = mkmsg("sending '%s' (%d KB)", ptn, sz / 1024);
183
184 a = queue_action(OP_COMMAND, "flash:%s", ptn);
185 a->msg = mkmsg("writing '%s'", ptn);
186}
在看queue_action的实现,将要写到板子里面的数据的size和data封装到Action中。
最后在fastboot.cpp 的1298行执行这些Action
1298 status = fb_execute_queue(usb);
int fb_execute_queue(usb_handle *usb)
368{
369 Action *a;
370 char resp[FB_RESPONSE_SZ+1];
371 int status = 0;
372
373 a = action_list;
374 if (!a)
375 return status;
376 resp[FB_RESPONSE_SZ] = 0;
377
378 double start = -1;
379 for (a = action_list; a; a = a->next) {
380 a->start = now();
381 if (start < 0) start = a->start;
382 if (a->msg) {
383 // fprintf(stderr,"%30s... ",a->msg);
384 fprintf(stderr,"%s...\n",a->msg);
385 }
386 if (a->op == OP_DOWNLOAD) {
387 status = fb_download_data(usb, a->data, a->size);
388 status = a->func(a, status, status ? fb_get_error() : "");
389 if (status) break;
390 } else if (a->op == OP_COMMAND) {
391 status = fb_command(usb, a->cmd);
392 status = a->func(a, status, status ? fb_get_error() : "");
393 if (status) break;
394 } else if (a->op == OP_QUERY) {
395 status = fb_command_response(usb, a->cmd, resp);
396 status = a->func(a, status, status ? fb_get_error() : resp);
397 if (status) break;
398 } else if (a->op == OP_NOTICE) {
399 fprintf(stderr,"%s\n",(char*)a->data);
400 } else if (a->op == OP_DOWNLOAD_SPARSE) {
401 status = fb_download_data_sparse(usb, a->data);
402 status = a->func(a, status, status ? fb_get_error() : "");
403 if (status) break;
404 } else if (a->op == OP_WAIT_FOR_DISCONNECT) {
405 usb_wait_for_disconnect(usb);
406 } else {
407 die("bogus action");
408 }
409 }
410
411 fprintf(stderr,"finished. total time: %.3fs\n", (now() - start));
412 return status;
413}
我们在fb_queue_flash中封装了两个ACTION,一个是OP_DOWNLOAD,一个是OP_COMMAND。这两个函数func是cb_default,仅仅是一个用于显示函数.
OP_DOWNLOAD就调用 fb_download_data->_command_send 通过usb将数据发送出去了
204int fb_download_data(usb_handle *usb, const void *data, unsigned size)
205{
206 char cmd[64];
207 int r;
208
209 sprintf(cmd, "download:%08x", size);
210 r = _command_send(usb, cmd, data, size, 0);
211
212 if(r < 0) {
213 return -1;
214 } else {
215 return 0;
216 }
217}
_command_send 实现如下:
161static int _command_send(usb_handle *usb, const char *cmd,
162 const void *data, unsigned size,
163 char *response)
164{
165 int r;
166 if (size == 0) {
167 return -1;
168 }
169
170 r = _command_start(usb, cmd, size, response);
171 if (r < 0) {
172 return -1;
173 }
174
175 r = _command_data(usb, data, size);
176 if (r < 0) {
177 return -1;
178 }
179
180 r = _command_end(usb);
181 if(r < 0) {
182 return -1;
183 }
184
185 return size;
186}
_command_start 实现如下:
109static int _command_start(usb_handle *usb, const char *cmd, unsigned size,
110 char *response)
111{
112 int cmdsize = strlen(cmd);
113
114 if(response) {
115 response[0] = 0;
116 }
117
118 if(cmdsize > 64) {
119 sprintf(ERROR,"command too large");
120 return -1;
121 }
122
123 if(usb_write(usb, cmd, cmdsize) != cmdsize) {
124 sprintf(ERROR,"command write failed (%s)", strerror(errno));
125 usb_close(usb);
126 return -1;
127 }
128
129 return check_response(usb, size, response);
130}
在_command_start 中终于看到usb_write了,所以就是我们分析整个flash命令的执行过程。希望可以抛砖引玉.
首先看Android.mk,可以fastboot用的源文件protocol.c engine.c bootimg_utils.cpp fastboot.cpp util.c fs.c
这些源文件和lib会被build一个fastboot 的可执行bin档(include $(BUILD_HOST_EXECUTABLE)).
xref: /system/core/fastboot/Android.mk
1LOCAL_C_INCLUDES := $(LOCAL_PATH)/../mkbootimg \
22 $(LOCAL_PATH)/../../extras/ext4_utils \
23 $(LOCAL_PATH)/../../extras/f2fs_utils
24LOCAL_SRC_FILES := protocol.c engine.c bootimg_utils.cpp fastboot.cpp util.c fs.c
25LOCAL_MODULE := fastboot
26LOCAL_MODULE_TAGS := debug
27LOCAL_CONLYFLAGS += -std=gnu99
28LOCAL_CFLAGS += -Wall -Wextra -Werror -Wunreachable-code
由下面这段可以fastboot 可以support的host为linux/darwin/window.
32ifeq ($(HOST_OS),linux)
33 LOCAL_SRC_FILES += usb_linux.c util_linux.c
34endif
35
36ifeq ($(HOST_OS),darwin)
37 LOCAL_SRC_FILES += usb_osx.c util_osx.c
38 LOCAL_LDLIBS += -lpthread -framework CoreFoundation -framework IOKit -framework Carbon
39 LOCAL_CFLAGS += -Wno-unused-parameter
40endif
41
42ifeq ($(HOST_OS),windows)
43 LOCAL_SRC_FILES += usb_windows.c util_windows.c
有43行可以usb_windows.c util_windows.c 是用于通过usb 给板子发送命令的.
既然fastboot 是一个可以执行的bin,那我们来看看其main函数的实现。
xref: /system/core/fastboot/fastboot.cpp
int main(int argc, char **argv)
1006{
1114
1115 if (argc > 0 && !strcmp(*argv, "devices")) {
1116 skip(1);
1117 list_devices();
1118 return 0;
1119 }
1120
1121 if (argc > 0 && !strcmp(*argv, "help")) {
1122 usage();
1123 return 0;
1124 }
1125
1126 usb_handle* usb = open_device();
1127
1128 while (argc > 0) {
1129 if(!strcmp(*argv, "getvar")) {
1130 require(2);
1131 fb_queue_display(argv[1], argv[1]);
1132 skip(2);
1133 } else if(!strcmp(*argv, "erase")) {
1134 require(2);
1135
1136 if (fb_format_supported(usb, argv[1], NULL)) {
1137 fprintf(stderr, "******** Did you mean to fastboot format this partition?\n");
1138 }
1139
1140 fb_queue_erase(argv[1]);
1141 skip(2);
1142 } else if(!strncmp(*argv, "format", strlen("format"))) {
1143 char *overrides;
1144 char *type_override = NULL;
1145 char *size_override = NULL;
1146 require(2);
1156 overrides = strchr(*argv, ':');
1157 if (overrides) {
1158 overrides++;
1159 size_override = strchr(overrides, ':');
1160 if (size_override) {
1161 size_override[0] = '\0';
1162 size_override++;
1163 }
1164 type_override = overrides;
1165 }
1166 if (type_override && !type_override[0]) type_override = NULL;
1167 if (size_override && !size_override[0]) size_override = NULL;
1168 if (erase_first && needs_erase(usb, argv[1])) {
1169 fb_queue_erase(argv[1]);
1170 }
1171 fb_perform_format(usb, argv[1], 0, type_override, size_override);
1172 skip(2);
1173 } else if(!strcmp(*argv, "signature")) {
1174 require(2);
1175 data = load_file(argv[1], &sz);
1176 if (data == 0) die("could not load '%s': %s", argv[1], strerror(errno));
1177 if (sz != 256) die("signature must be 256 bytes");
1178 fb_queue_download("signature", data, sz);
1179 fb_queue_command("signature", "installing signature");
1180 skip(2);
1181 } else if(!strcmp(*argv, "reboot")) {
1182 wants_reboot = 1;
1183 skip(1);
1184 if (argc > 0) {
1185 if (!strcmp(*argv, "bootloader")) {
1186 wants_reboot = 0;
1187 wants_reboot_bootloader = 1;
1188 skip(1);
1189 }
1190 }
1191 require(0);
1192 } else if(!strcmp(*argv, "reboot-bootloader")) {
1193 wants_reboot_bootloader = 1;
1194 skip(1);
1195 } else if (!strcmp(*argv, "continue")) {
1196 fb_queue_command("continue", "resuming boot");
1197 skip(1);
1198 } else if(!strcmp(*argv, "boot")) {
1199 char *kname = 0;
1200 char *rname = 0;
1201 skip(1);
1202 if (argc > 0) {
1203 kname = argv[0];
1204 skip(1);
1205 }
1206 if (argc > 0) {
1207 rname = argv[0];
1208 skip(1);
1209 }
1210 data = load_bootable_image(kname, rname, &sz, cmdline);
1211 if (data == 0) return 1;
1212 fb_queue_download("boot.img", data, sz);
1213 fb_queue_command("boot", "booting");
1214 } else if(!strcmp(*argv, "flash")) {
1215 char *pname = argv[1];
1216 char *fname = 0;
1217 require(2);
1218 if (argc > 2) {
1219 fname = argv[2];
1220 skip(3);
1221 } else {
1222 fname = find_item(pname, product);
1223 skip(2);
1224 }
1225 if (fname == 0) die("cannot determine image filename for '%s'", pname);
1226 if (erase_first && needs_erase(usb, pname)) {
1227 fb_queue_erase(pname);
1228 }
1229 do_flash(usb, pname, fname);
1294
1295 if (fb_queue_is_empty())
1296 return 0;
1297
1298 status = fb_execute_queue(usb);
1299 return (status) ? 1 : 0;
1300}
1126行是打开usb设备用于通讯,如我们所分析,因为我们用的host是window,所以实在usb_windows.c 实现.
H A D usb_windows.c 49 AdbWinApi.dll. This structure is returned from usb_open() routine and
376 usb_handle *usb_open(ifc_match_func callback) function
从1128行开始就是fastboot的命令。
我们以fastboot flash命令为例。
会执行1214行的flash命令。最终调用1229行的do_flash函数。
xref: /system/core/fastboot/fastboot.cpp
720void do_flash(usb_handle *usb, const char *pname, const char *fname)
721{
722 struct fastboot_buffer buf;
723
724 if (load_buf(usb, fname, &buf)) {
725 die("cannot load '%s'", fname);
726 }
727 flash_buf(pname, &buf);
728}
可见先调用724行的load_buf将数据读进来。下打开这个文件获取到fd,在根据fd来读文件.
687static int load_buf(usb_handle *usb, const char *fname,
688 struct fastboot_buffer *buf)
689{
690 int fd;
691
692 fd = open(fname, O_RDONLY | O_BINARY);
693 if (fd < 0) {
694 return -1;
695 }
696
697 return load_buf_fd(usb, fd, buf);
698}
其次调用来准备发送数据,可见支持FB_BUFFER_SPARSE 和 FB_BUFFER是(ext4 support的两种格式)
700static void flash_buf(const char *pname, struct fastboot_buffer *buf)
701{
702 sparse_file** s;
703
704 switch (buf->type) {
705 case FB_BUFFER_SPARSE:
706 s = reinterpret_cast<sparse_file**>(buf->data);
707 while (*s) {
708 int64_t sz64 = sparse_file_len(*s, true, false);
709 fb_queue_flash_sparse(pname, *s++, sz64);
710 }
711 break;
712 case FB_BUFFER:
713 fb_queue_flash(pname, buf->data, buf->sz);
714 break;
715 default:
716 die("unknown buffer type: %d", buf->type);
717 }
718}
我们以FB_BUFEER为例,调用fb_queue_flash(pname, buf->data, buf->sz); 来将要做的事情加入到列表中
175void fb_queue_flash(const char *ptn, void *data, unsigned sz)
176{
177 Action *a;
178
179 a = queue_action(OP_DOWNLOAD, "");
180 a->data = data;
181 a->size = sz;
182 a->msg = mkmsg("sending '%s' (%d KB)", ptn, sz / 1024);
183
184 a = queue_action(OP_COMMAND, "flash:%s", ptn);
185 a->msg = mkmsg("writing '%s'", ptn);
186}
在看queue_action的实现,将要写到板子里面的数据的size和data封装到Action中。
最后在fastboot.cpp 的1298行执行这些Action
1298 status = fb_execute_queue(usb);
int fb_execute_queue(usb_handle *usb)
368{
369 Action *a;
370 char resp[FB_RESPONSE_SZ+1];
371 int status = 0;
372
373 a = action_list;
374 if (!a)
375 return status;
376 resp[FB_RESPONSE_SZ] = 0;
377
378 double start = -1;
379 for (a = action_list; a; a = a->next) {
380 a->start = now();
381 if (start < 0) start = a->start;
382 if (a->msg) {
383 // fprintf(stderr,"%30s... ",a->msg);
384 fprintf(stderr,"%s...\n",a->msg);
385 }
386 if (a->op == OP_DOWNLOAD) {
387 status = fb_download_data(usb, a->data, a->size);
388 status = a->func(a, status, status ? fb_get_error() : "");
389 if (status) break;
390 } else if (a->op == OP_COMMAND) {
391 status = fb_command(usb, a->cmd);
392 status = a->func(a, status, status ? fb_get_error() : "");
393 if (status) break;
394 } else if (a->op == OP_QUERY) {
395 status = fb_command_response(usb, a->cmd, resp);
396 status = a->func(a, status, status ? fb_get_error() : resp);
397 if (status) break;
398 } else if (a->op == OP_NOTICE) {
399 fprintf(stderr,"%s\n",(char*)a->data);
400 } else if (a->op == OP_DOWNLOAD_SPARSE) {
401 status = fb_download_data_sparse(usb, a->data);
402 status = a->func(a, status, status ? fb_get_error() : "");
403 if (status) break;
404 } else if (a->op == OP_WAIT_FOR_DISCONNECT) {
405 usb_wait_for_disconnect(usb);
406 } else {
407 die("bogus action");
408 }
409 }
410
411 fprintf(stderr,"finished. total time: %.3fs\n", (now() - start));
412 return status;
413}
我们在fb_queue_flash中封装了两个ACTION,一个是OP_DOWNLOAD,一个是OP_COMMAND。这两个函数func是cb_default,仅仅是一个用于显示函数.
OP_DOWNLOAD就调用 fb_download_data->_command_send 通过usb将数据发送出去了
204int fb_download_data(usb_handle *usb, const void *data, unsigned size)
205{
206 char cmd[64];
207 int r;
208
209 sprintf(cmd, "download:%08x", size);
210 r = _command_send(usb, cmd, data, size, 0);
211
212 if(r < 0) {
213 return -1;
214 } else {
215 return 0;
216 }
217}
_command_send 实现如下:
161static int _command_send(usb_handle *usb, const char *cmd,
162 const void *data, unsigned size,
163 char *response)
164{
165 int r;
166 if (size == 0) {
167 return -1;
168 }
169
170 r = _command_start(usb, cmd, size, response);
171 if (r < 0) {
172 return -1;
173 }
174
175 r = _command_data(usb, data, size);
176 if (r < 0) {
177 return -1;
178 }
179
180 r = _command_end(usb);
181 if(r < 0) {
182 return -1;
183 }
184
185 return size;
186}
_command_start 实现如下:
109static int _command_start(usb_handle *usb, const char *cmd, unsigned size,
110 char *response)
111{
112 int cmdsize = strlen(cmd);
113
114 if(response) {
115 response[0] = 0;
116 }
117
118 if(cmdsize > 64) {
119 sprintf(ERROR,"command too large");
120 return -1;
121 }
122
123 if(usb_write(usb, cmd, cmdsize) != cmdsize) {
124 sprintf(ERROR,"command write failed (%s)", strerror(errno));
125 usb_close(usb);
126 return -1;
127 }
128
129 return check_response(usb, size, response);
130}
在_command_start 中终于看到usb_write了,所以就是我们分析整个flash命令的执行过程。希望可以抛砖引玉.