Home | History | Annotate | Download | only in fs_mgr
      1 /*
      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.
     37 static 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 
     81 // 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.
     84 static int get_active_slot_suffix(struct fstab *fstab, char *out_suffix,
     85                                   size_t suffix_len)
     86 {
     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);
     95         return 0;
     96     }
     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);
    102         return 0;
    103     }
    104 
    105     ERROR("Error determining slot_suffix\n");
    106 
    107     return -1;
    108 }
    109 
    110 // Updates |fstab| for slot_suffix. Returns 0 on success, -1 on error.
    111 int 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));
    123                 if (get_active_slot_suffix(fstab, suffix,
    124                                            sizeof(suffix) - 1) != 0) {
    125                   return -1;
    126                 }
    127                 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 }
    141