blob: ca07b189ba8f6d5ff52b29ecc0815a1cd64425c5 [file] [log] [blame]
David Zeuthen227ef3c2015-09-03 12:23:12 -04001/*
2 * Copyright (C) 2015 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#include <fcntl.h>
18#include <sys/types.h>
19#include <sys/stat.h>
20#include <unistd.h>
21
22#include <ctype.h>
23#include <errno.h>
24#include <stdio.h>
25#include <stdlib.h>
26#include <string.h>
27
28#include <cutils/properties.h>
29
30#include "fs_mgr.h"
31#include "fs_mgr_priv.h"
32
33#include "bootloader.h"
34
35// Copies slot_suffix from misc into |out_suffix|. Returns 0 on
36// success, -1 on error or if there is no non-empty slot_suffix.
37static int get_active_slot_suffix_from_misc(struct fstab *fstab,
38 char *out_suffix,
39 size_t suffix_len)
40{
41 int n;
42 int misc_fd;
43 ssize_t num_read;
44 struct bootloader_message msg;
45
46 misc_fd = -1;
47 for (n = 0; n < fstab->num_entries; n++) {
48 if (strcmp(fstab->recs[n].mount_point, "/misc") == 0) {
49 misc_fd = open(fstab->recs[n].blk_device, O_RDONLY);
50 if (misc_fd == -1) {
51 ERROR("Error opening misc partition \"%s\" (%s)\n",
52 fstab->recs[n].blk_device,
53 strerror(errno));
54 return -1;
55 } else {
56 break;
57 }
58 }
59 }
60
61 if (misc_fd == -1) {
62 ERROR("Error finding misc partition\n");
63 return -1;
64 }
65
66 num_read = TEMP_FAILURE_RETRY(read(misc_fd, &msg, sizeof(msg)));
67 // Linux will never return partial reads when reading from block
68 // devices so no need to worry about them.
69 if (num_read != sizeof(msg)) {
70 ERROR("Error reading bootloader_message (%s)\n", strerror(errno));
71 close(misc_fd);
72 return -1;
73 }
74 close(misc_fd);
75 if (msg.slot_suffix[0] == '\0')
76 return -1;
77 strncpy(out_suffix, msg.slot_suffix, suffix_len);
78 return 0;
79}
80
David Zeuthenbd0231c2015-09-09 18:15:11 -040081// Gets slot_suffix from either the kernel cmdline / firmware or the
82// misc partition. Sets |out_suffix| on success and returns 0. Returns
83// -1 if slot_suffix could not be determined.
84static int get_active_slot_suffix(struct fstab *fstab, char *out_suffix,
85 size_t suffix_len)
David Zeuthen227ef3c2015-09-03 12:23:12 -040086{
87 char propbuf[PROPERTY_VALUE_MAX];
88
89 // Get the suffix from the kernel commandline (note that we don't
90 // allow the empty suffix). On bootloaders natively supporting A/B
91 // we'll hit this path every time so don't bother logging it.
92 property_get("ro.boot.slot_suffix", propbuf, "");
93 if (propbuf[0] != '\0') {
94 strncpy(out_suffix, propbuf, suffix_len);
David Zeuthenbd0231c2015-09-09 18:15:11 -040095 return 0;
David Zeuthen227ef3c2015-09-03 12:23:12 -040096 }
97
98 // If we couldn't get the suffix from the kernel cmdline, try the
99 // the misc partition.
100 if (get_active_slot_suffix_from_misc(fstab, out_suffix, suffix_len) == 0) {
101 INFO("Using slot suffix \"%s\" from misc\n", out_suffix);
David Zeuthenbd0231c2015-09-09 18:15:11 -0400102 return 0;
David Zeuthen227ef3c2015-09-03 12:23:12 -0400103 }
104
David Zeuthenbd0231c2015-09-09 18:15:11 -0400105 ERROR("Error determining slot_suffix\n");
106
107 return -1;
David Zeuthen227ef3c2015-09-03 12:23:12 -0400108}
109
110// Updates |fstab| for slot_suffix. Returns 0 on success, -1 on error.
111int fs_mgr_update_for_slotselect(struct fstab *fstab)
112{
113 int n;
114 char suffix[PROPERTY_VALUE_MAX];
115 int got_suffix = 0;
116
117 for (n = 0; n < fstab->num_entries; n++) {
118 if (fstab->recs[n].fs_mgr_flags & MF_SLOTSELECT) {
119 char *tmp;
120
121 if (!got_suffix) {
122 memset(suffix, '\0', sizeof(suffix));
David Zeuthenbd0231c2015-09-09 18:15:11 -0400123 if (get_active_slot_suffix(fstab, suffix,
124 sizeof(suffix) - 1) != 0) {
125 return -1;
126 }
David Zeuthen227ef3c2015-09-03 12:23:12 -0400127 got_suffix = 1;
128 }
129
130 if (asprintf(&tmp, "%s%s", fstab->recs[n].blk_device,
131 suffix) > 0) {
132 free(fstab->recs[n].blk_device);
133 fstab->recs[n].blk_device = tmp;
134 } else {
135 return -1;
136 }
137 }
138 }
139 return 0;
140}