1*288bf522SAndroid Build Coastguard Worker /*
2*288bf522SAndroid Build Coastguard Worker * Copyright (C) 2015 The Android Open Source Project
3*288bf522SAndroid Build Coastguard Worker *
4*288bf522SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*288bf522SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*288bf522SAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*288bf522SAndroid Build Coastguard Worker *
8*288bf522SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*288bf522SAndroid Build Coastguard Worker *
10*288bf522SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*288bf522SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*288bf522SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*288bf522SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*288bf522SAndroid Build Coastguard Worker * limitations under the License.
15*288bf522SAndroid Build Coastguard Worker */
16*288bf522SAndroid Build Coastguard Worker
17*288bf522SAndroid Build Coastguard Worker #include <errno.h>
18*288bf522SAndroid Build Coastguard Worker #include <fcntl.h>
19*288bf522SAndroid Build Coastguard Worker #include <linux/fs.h>
20*288bf522SAndroid Build Coastguard Worker #include <sys/ioctl.h>
21*288bf522SAndroid Build Coastguard Worker #include <sys/stat.h>
22*288bf522SAndroid Build Coastguard Worker #include <sys/types.h>
23*288bf522SAndroid Build Coastguard Worker #include <unistd.h>
24*288bf522SAndroid Build Coastguard Worker
25*288bf522SAndroid Build Coastguard Worker #include <arpa/inet.h>
26*288bf522SAndroid Build Coastguard Worker #include <stdio.h>
27*288bf522SAndroid Build Coastguard Worker #include <stdlib.h>
28*288bf522SAndroid Build Coastguard Worker #include <string.h>
29*288bf522SAndroid Build Coastguard Worker
30*288bf522SAndroid Build Coastguard Worker #include <cutils/properties.h>
31*288bf522SAndroid Build Coastguard Worker #include <fs_mgr.h>
32*288bf522SAndroid Build Coastguard Worker
33*288bf522SAndroid Build Coastguard Worker #include "bootinfo.h"
34*288bf522SAndroid Build Coastguard Worker
35*288bf522SAndroid Build Coastguard Worker using android::fs_mgr::Fstab;
36*288bf522SAndroid Build Coastguard Worker using android::fs_mgr::GetEntryForMountPoint;
37*288bf522SAndroid Build Coastguard Worker using android::fs_mgr::ReadDefaultFstab;
38*288bf522SAndroid Build Coastguard Worker using android::fs_mgr::ReadFstabFromFile;
39*288bf522SAndroid Build Coastguard Worker
40*288bf522SAndroid Build Coastguard Worker // Open the appropriate fstab file and fallback to /fstab.device if
41*288bf522SAndroid Build Coastguard Worker // that's what's being used.
open_fstab(Fstab * fstab)42*288bf522SAndroid Build Coastguard Worker static bool open_fstab(Fstab* fstab) {
43*288bf522SAndroid Build Coastguard Worker return ReadDefaultFstab(fstab) || ReadFstabFromFile("/fstab.device", fstab);
44*288bf522SAndroid Build Coastguard Worker }
45*288bf522SAndroid Build Coastguard Worker
boot_info_open_partition(const char * name,uint64_t * out_size,int flags)46*288bf522SAndroid Build Coastguard Worker int boot_info_open_partition(const char* name, uint64_t* out_size, int flags) {
47*288bf522SAndroid Build Coastguard Worker char* path;
48*288bf522SAndroid Build Coastguard Worker int fd;
49*288bf522SAndroid Build Coastguard Worker
50*288bf522SAndroid Build Coastguard Worker // We can't use fs_mgr to look up |name| because fstab doesn't list
51*288bf522SAndroid Build Coastguard Worker // every slot partition (it uses the slotselect option to mask the
52*288bf522SAndroid Build Coastguard Worker // suffix) and |slot| is expected to be of that form, e.g. boot_a.
53*288bf522SAndroid Build Coastguard Worker //
54*288bf522SAndroid Build Coastguard Worker // We can however assume that there's an entry for the /misc mount
55*288bf522SAndroid Build Coastguard Worker // point and use that to get the device file for the misc
56*288bf522SAndroid Build Coastguard Worker // partition. From there we'll assume that a by-name scheme is used
57*288bf522SAndroid Build Coastguard Worker // so we can just replace the trailing "misc" by the given |name|,
58*288bf522SAndroid Build Coastguard Worker // e.g.
59*288bf522SAndroid Build Coastguard Worker //
60*288bf522SAndroid Build Coastguard Worker // /dev/block/platform/soc.0/7824900.sdhci/by-name/misc ->
61*288bf522SAndroid Build Coastguard Worker // /dev/block/platform/soc.0/7824900.sdhci/by-name/boot_a
62*288bf522SAndroid Build Coastguard Worker //
63*288bf522SAndroid Build Coastguard Worker // If needed, it's possible to relax this assumption in the future
64*288bf522SAndroid Build Coastguard Worker // by trawling /sys/block looking for the appropriate sibling of
65*288bf522SAndroid Build Coastguard Worker // misc and then finding an entry in /dev matching the sysfs entry.
66*288bf522SAndroid Build Coastguard Worker
67*288bf522SAndroid Build Coastguard Worker Fstab fstab;
68*288bf522SAndroid Build Coastguard Worker if (!open_fstab(&fstab)) {
69*288bf522SAndroid Build Coastguard Worker return -1;
70*288bf522SAndroid Build Coastguard Worker }
71*288bf522SAndroid Build Coastguard Worker auto record = GetEntryForMountPoint(&fstab, "/misc");
72*288bf522SAndroid Build Coastguard Worker if (record == nullptr) {
73*288bf522SAndroid Build Coastguard Worker return -1;
74*288bf522SAndroid Build Coastguard Worker }
75*288bf522SAndroid Build Coastguard Worker if (strcmp(name, "misc") == 0) {
76*288bf522SAndroid Build Coastguard Worker path = strdup(record->blk_device.c_str());
77*288bf522SAndroid Build Coastguard Worker } else {
78*288bf522SAndroid Build Coastguard Worker size_t trimmed_len, name_len;
79*288bf522SAndroid Build Coastguard Worker const char* end_slash = strrchr(record->blk_device.c_str(), '/');
80*288bf522SAndroid Build Coastguard Worker if (end_slash == NULL) {
81*288bf522SAndroid Build Coastguard Worker return -1;
82*288bf522SAndroid Build Coastguard Worker }
83*288bf522SAndroid Build Coastguard Worker trimmed_len = end_slash - record->blk_device.c_str() + 1;
84*288bf522SAndroid Build Coastguard Worker name_len = strlen(name);
85*288bf522SAndroid Build Coastguard Worker path = static_cast<char*>(calloc(trimmed_len + name_len + 1, 1));
86*288bf522SAndroid Build Coastguard Worker strncpy(path, record->blk_device.c_str(), trimmed_len);
87*288bf522SAndroid Build Coastguard Worker strncpy(path + trimmed_len, name, name_len);
88*288bf522SAndroid Build Coastguard Worker }
89*288bf522SAndroid Build Coastguard Worker
90*288bf522SAndroid Build Coastguard Worker fd = open(path, flags);
91*288bf522SAndroid Build Coastguard Worker free(path);
92*288bf522SAndroid Build Coastguard Worker
93*288bf522SAndroid Build Coastguard Worker // If we successfully opened the device, get size if requested.
94*288bf522SAndroid Build Coastguard Worker if (fd != -1 && out_size != NULL) {
95*288bf522SAndroid Build Coastguard Worker if (ioctl(fd, BLKGETSIZE64, out_size) != 0) {
96*288bf522SAndroid Build Coastguard Worker close(fd);
97*288bf522SAndroid Build Coastguard Worker return -1;
98*288bf522SAndroid Build Coastguard Worker }
99*288bf522SAndroid Build Coastguard Worker }
100*288bf522SAndroid Build Coastguard Worker
101*288bf522SAndroid Build Coastguard Worker return fd;
102*288bf522SAndroid Build Coastguard Worker }
103*288bf522SAndroid Build Coastguard Worker
104*288bf522SAndroid Build Coastguard Worker // As per struct bootloader_message_ab which is defined in
105*288bf522SAndroid Build Coastguard Worker // boot/1.1/default.
106*288bf522SAndroid Build Coastguard Worker // struct bootloader_message_ab {
107*288bf522SAndroid Build Coastguard Worker // struct bootloader_message message;
108*288bf522SAndroid Build Coastguard Worker // char slot_suffix[32];
109*288bf522SAndroid Build Coastguard Worker // char update_channel[128];
110*288bf522SAndroid Build Coastguard Worker //
111*288bf522SAndroid Build Coastguard Worker // // Round up the entire struct to 4096-byte.
112*288bf522SAndroid Build Coastguard Worker // char reserved[1888];
113*288bf522SAndroid Build Coastguard Worker // };
114*288bf522SAndroid Build Coastguard Worker //
115*288bf522SAndroid Build Coastguard Worker // We can use the 32 bytes in the bootctrl_suffix field provided that they
116*288bf522SAndroid Build Coastguard Worker // start with the active slot suffix terminated by NUL. It just so happens
117*288bf522SAndroid Build Coastguard Worker // that BrilloBootInfo is laid out this way.
118*288bf522SAndroid Build Coastguard Worker #define BOOTINFO_OFFSET 2048
119*288bf522SAndroid Build Coastguard Worker
boot_info_load(BrilloBootInfo * out_info)120*288bf522SAndroid Build Coastguard Worker bool boot_info_load(BrilloBootInfo* out_info) {
121*288bf522SAndroid Build Coastguard Worker int fd;
122*288bf522SAndroid Build Coastguard Worker
123*288bf522SAndroid Build Coastguard Worker memset(out_info, '\0', sizeof(BrilloBootInfo));
124*288bf522SAndroid Build Coastguard Worker
125*288bf522SAndroid Build Coastguard Worker fd = boot_info_open_partition("misc", NULL, O_RDONLY);
126*288bf522SAndroid Build Coastguard Worker if (fd == -1) return false;
127*288bf522SAndroid Build Coastguard Worker if (lseek(fd, BOOTINFO_OFFSET, SEEK_SET) != BOOTINFO_OFFSET) {
128*288bf522SAndroid Build Coastguard Worker close(fd);
129*288bf522SAndroid Build Coastguard Worker return false;
130*288bf522SAndroid Build Coastguard Worker }
131*288bf522SAndroid Build Coastguard Worker ssize_t num_read;
132*288bf522SAndroid Build Coastguard Worker do {
133*288bf522SAndroid Build Coastguard Worker num_read = read(fd, (void*)out_info, sizeof(BrilloBootInfo));
134*288bf522SAndroid Build Coastguard Worker } while (num_read == -1 && errno == EINTR);
135*288bf522SAndroid Build Coastguard Worker close(fd);
136*288bf522SAndroid Build Coastguard Worker if (num_read != sizeof(BrilloBootInfo)) return false;
137*288bf522SAndroid Build Coastguard Worker return true;
138*288bf522SAndroid Build Coastguard Worker }
139*288bf522SAndroid Build Coastguard Worker
boot_info_save(BrilloBootInfo * info)140*288bf522SAndroid Build Coastguard Worker bool boot_info_save(BrilloBootInfo* info) {
141*288bf522SAndroid Build Coastguard Worker int fd;
142*288bf522SAndroid Build Coastguard Worker
143*288bf522SAndroid Build Coastguard Worker fd = boot_info_open_partition("misc", NULL, O_RDWR);
144*288bf522SAndroid Build Coastguard Worker if (fd == -1) return false;
145*288bf522SAndroid Build Coastguard Worker if (lseek(fd, BOOTINFO_OFFSET, SEEK_SET) != BOOTINFO_OFFSET) {
146*288bf522SAndroid Build Coastguard Worker close(fd);
147*288bf522SAndroid Build Coastguard Worker return false;
148*288bf522SAndroid Build Coastguard Worker }
149*288bf522SAndroid Build Coastguard Worker ssize_t num_written;
150*288bf522SAndroid Build Coastguard Worker do {
151*288bf522SAndroid Build Coastguard Worker num_written = write(fd, (void*)info, sizeof(BrilloBootInfo));
152*288bf522SAndroid Build Coastguard Worker } while (num_written == -1 && errno == EINTR);
153*288bf522SAndroid Build Coastguard Worker close(fd);
154*288bf522SAndroid Build Coastguard Worker if (num_written != sizeof(BrilloBootInfo)) return false;
155*288bf522SAndroid Build Coastguard Worker return true;
156*288bf522SAndroid Build Coastguard Worker }
157*288bf522SAndroid Build Coastguard Worker
boot_info_validate(BrilloBootInfo * info)158*288bf522SAndroid Build Coastguard Worker bool boot_info_validate(BrilloBootInfo* info) {
159*288bf522SAndroid Build Coastguard Worker if (info->magic[0] != 'B' || info->magic[1] != 'C' || info->magic[2] != 'c') return false;
160*288bf522SAndroid Build Coastguard Worker if (info->active_slot >= 2) return false;
161*288bf522SAndroid Build Coastguard Worker return true;
162*288bf522SAndroid Build Coastguard Worker }
163*288bf522SAndroid Build Coastguard Worker
boot_info_reset(BrilloBootInfo * info)164*288bf522SAndroid Build Coastguard Worker void boot_info_reset(BrilloBootInfo* info) {
165*288bf522SAndroid Build Coastguard Worker memset(info, '\0', sizeof(BrilloBootInfo));
166*288bf522SAndroid Build Coastguard Worker info->magic[0] = 'B';
167*288bf522SAndroid Build Coastguard Worker info->magic[1] = 'C';
168*288bf522SAndroid Build Coastguard Worker info->magic[2] = 'c';
169*288bf522SAndroid Build Coastguard Worker }
170