1 /*
2 * Copyright 2016 Google Inc. All Rights Reserved.
3 * Author: gkalsi@google.com (Gurjant Kalsi)
4 *
5 * Use of this source code is governed by a MIT-style
6 * license that can be found in the LICENSE file or at
7 * https://opensource.org/licenses/MIT
8 */
9
10 #include <app/moot/fsboot.h>
11 #include <app/moot/stubs.h>
12 #include <lk/compiler.h>
13 #include <lk/err.h>
14 #include <lib/bio.h>
15 #include <lib/bootimage.h>
16 #include <lib/fs.h>
17 #include <stdio.h>
18 #include <lk/trace.h>
19
20 #define MAX_FPATH_LEN 64
21
22 #define LOCAL_TRACE 0
23
24 // Attempt to boot from the filesystem.
attempt_fs_boot(void)25 void attempt_fs_boot(void) {
26 char *mount_path, *device_name;
27 bootimage_t *bi;
28
29 status_t retcode = moot_mount_default_fs(&mount_path, &device_name);
30 if (retcode != NO_ERROR) {
31 LTRACEF("Failed: Unable to mount default fs. retcode = %d\n", retcode);
32 return;
33 }
34
35 char fpath[MAX_FPATH_LEN];
36 snprintf(fpath, MAX_FPATH_LEN, "%s/system.img", mount_path);
37
38 filehandle *handle;
39 retcode = fs_open_file(fpath, &handle);
40 if (retcode != NO_ERROR) {
41 LTRACEF("Failed: to open recovery file: '%s'. retcode = %d\n",
42 fpath,retcode);
43 goto finish;
44 }
45
46 // Fill in the length of the bootimage
47 struct file_stat stat;
48 retcode = fs_stat_file(handle, &stat);
49 if (retcode != NO_ERROR) {
50 LTRACEF("Failed: to stat recovery file: '%s'. retcode = %d\n",
51 fpath,retcode);
52 goto finish;
53 }
54
55 // Get the address of the Bootimage.
56 // TODO: At some point we might have a flash device/controller that doesn't
57 // support linear mode. In that case we'll have to come up with a mechanism
58 // that can verify a bootimg without memory mapping the file.
59 unsigned char *address = 0;
60 retcode = fs_file_ioctl(handle, FS_IOCTL_GET_FILE_ADDR, &address);
61 fs_close_file(handle);
62
63 if (retcode != NO_ERROR) {
64 LTRACEF("Failed: to get file memmap for '%s'. retcode = %d\n",
65 fpath,retcode);
66 goto finish;
67 }
68
69 bdev_t *secondary_flash = bio_open(device_name);
70 if (!secondary_flash) {
71 LTRACEF("Failed: Unable to open secondary flash at '%s'. "
72 "retcode = %d\n", device_name,retcode);
73 goto finish;
74 }
75
76 unsigned char *unused = 0;
77 retcode = bio_ioctl(secondary_flash, BIO_IOCTL_GET_MEM_MAP, &unused);
78 bio_close(secondary_flash);
79
80 if (retcode != NO_ERROR) {
81 LTRACEF("Failed: to get file memmap for '%s'. "
82 "retcode = %d\n", device_name,retcode);
83 goto finish;
84 }
85
86 retcode = bootimage_open(address, stat.size, &bi);
87 if (retcode != NO_ERROR) {
88 LTRACEF("Failed: Unable to open bootimage. retcode = %d\n",retcode);
89 goto finish;
90 }
91
92 size_t imglen;
93 const void *imgptr;
94 retcode = bootimage_get_file_section(bi, TYPE_LK, &imgptr, &imglen);
95 if (retcode != NO_ERROR) {
96 LTRACEF("Failed: Unable to find lk section. retcode = %d\n",retcode);
97 goto finish;
98 }
99
100 // Flash the new image.
101 bdev_t *system_flash = bio_open(moot_system_info.system_flash_name);
102 if (!system_flash) {
103 LTRACEF("Failed: Unable to open system flash at '%s'.\n",
104 moot_system_info.system_flash_name);
105 goto finish;
106 }
107
108 ssize_t n_bytes_erased =
109 bio_erase(system_flash, moot_system_info.system_offset, imglen);
110 if (n_bytes_erased < (ssize_t)imglen) {
111 LTRACEF("Failed: Unable to erase system flash at '%s'. retcode = %ld\n",
112 moot_system_info.system_flash_name, n_bytes_erased);
113 bio_close(system_flash);
114 goto finish;
115 }
116
117 ssize_t written =
118 bio_write(system_flash, imgptr, moot_system_info.system_offset, imglen);
119 bio_close(system_flash);
120
121 if (written < (ssize_t)imglen) {
122 LTRACEF("Failed: Unable to write system flash at '%s'. retcode = %ld\n",
123 moot_system_info.system_flash_name, written);
124 goto finish;
125 }
126
127 finish:
128 fs_unmount(mount_path);
129 }
130
131
132