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