Home | History | Annotate | Download | only in component
      1 /*
      2  * Copyright (C) 2016 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 <string>
     18 #include <vector>
     19 
     20 #include <android-base/strings.h>
     21 #include <bootloader_message/bootloader_message.h>
     22 #include <gtest/gtest.h>
     23 
     24 #include "common/component_test_util.h"
     25 
     26 class BootloaderMessageTest : public ::testing::Test {
     27  protected:
     28   BootloaderMessageTest() : has_misc(true) {}
     29 
     30   virtual void SetUp() override {
     31     has_misc = parse_misc();
     32   }
     33 
     34   virtual void TearDown() override {
     35     // Clear the BCB.
     36     if (has_misc) {
     37       std::string err;
     38       ASSERT_TRUE(clear_bootloader_message(&err)) << "Failed to clear BCB: " << err;
     39     }
     40   }
     41 
     42   bool has_misc;
     43 };
     44 
     45 TEST_F(BootloaderMessageTest, clear_bootloader_message) {
     46   if (!has_misc) {
     47     GTEST_LOG_(INFO) << "Test skipped due to no /misc partition found on the device.";
     48     return;
     49   }
     50 
     51   // Clear the BCB.
     52   std::string err;
     53   ASSERT_TRUE(clear_bootloader_message(&err)) << "Failed to clear BCB: " << err;
     54 
     55   // Verify the content.
     56   bootloader_message boot;
     57   ASSERT_TRUE(read_bootloader_message(&boot, &err)) << "Failed to read BCB: " << err;
     58 
     59   // All the bytes should be cleared.
     60   ASSERT_EQ(std::string(sizeof(boot), '\0'),
     61             std::string(reinterpret_cast<const char*>(&boot), sizeof(boot)));
     62 }
     63 
     64 TEST_F(BootloaderMessageTest, read_and_write_bootloader_message) {
     65   if (!has_misc) {
     66     GTEST_LOG_(INFO) << "Test skipped due to no /misc partition found on the device.";
     67     return;
     68   }
     69 
     70   // Write the BCB.
     71   bootloader_message boot = {};
     72   strlcpy(boot.command, "command", sizeof(boot.command));
     73   strlcpy(boot.recovery, "message1\nmessage2\n", sizeof(boot.recovery));
     74   strlcpy(boot.status, "status1", sizeof(boot.status));
     75 
     76   std::string err;
     77   ASSERT_TRUE(write_bootloader_message(boot, &err)) << "Failed to write BCB: " << err;
     78 
     79   // Read and verify.
     80   bootloader_message boot_verify;
     81   ASSERT_TRUE(read_bootloader_message(&boot_verify, &err)) << "Failed to read BCB: " << err;
     82 
     83   ASSERT_EQ(std::string(reinterpret_cast<const char*>(&boot), sizeof(boot)),
     84             std::string(reinterpret_cast<const char*>(&boot_verify), sizeof(boot_verify)));
     85 }
     86 
     87 TEST_F(BootloaderMessageTest, write_bootloader_message_options) {
     88   if (!has_misc) {
     89     GTEST_LOG_(INFO) << "Test skipped due to no /misc partition found on the device.";
     90     return;
     91   }
     92 
     93   // Write the options to BCB.
     94   std::vector<std::string> options = { "option1", "option2" };
     95   std::string err;
     96   ASSERT_TRUE(write_bootloader_message(options, &err)) << "Failed to write BCB: " << err;
     97 
     98   // Inject some bytes into boot, which should be overwritten while reading.
     99   bootloader_message boot;
    100   strlcpy(boot.recovery, "random message", sizeof(boot.recovery));
    101   strlcpy(boot.reserved, "reserved bytes", sizeof(boot.reserved));
    102 
    103   ASSERT_TRUE(read_bootloader_message(&boot, &err)) << "Failed to read BCB: " << err;
    104 
    105   // Verify that command and recovery fields should be set.
    106   ASSERT_EQ("boot-recovery", std::string(boot.command));
    107   std::string expected = "recovery\n" + android::base::Join(options, "\n") + "\n";
    108   ASSERT_EQ(expected, std::string(boot.recovery));
    109 
    110   // The rest should be cleared.
    111   ASSERT_EQ(std::string(sizeof(boot.status), '\0'), std::string(boot.status, sizeof(boot.status)));
    112   ASSERT_EQ(std::string(sizeof(boot.stage), '\0'), std::string(boot.stage, sizeof(boot.stage)));
    113   ASSERT_EQ(std::string(sizeof(boot.reserved), '\0'),
    114             std::string(boot.reserved, sizeof(boot.reserved)));
    115 }
    116 
    117 TEST_F(BootloaderMessageTest, write_bootloader_message_options_empty) {
    118   if (!has_misc) {
    119     GTEST_LOG_(INFO) << "Test skipped due to no /misc partition found on the device.";
    120     return;
    121   }
    122 
    123   // Write empty vector.
    124   std::vector<std::string> options;
    125   std::string err;
    126   ASSERT_TRUE(write_bootloader_message(options, &err)) << "Failed to write BCB: " << err;
    127 
    128   // Read and verify.
    129   bootloader_message boot;
    130   ASSERT_TRUE(read_bootloader_message(&boot, &err)) << "Failed to read BCB: " << err;
    131 
    132   // command and recovery fields should be set.
    133   ASSERT_EQ("boot-recovery", std::string(boot.command));
    134   ASSERT_EQ("recovery\n", std::string(boot.recovery));
    135 
    136   // The rest should be cleared.
    137   ASSERT_EQ(std::string(sizeof(boot.status), '\0'), std::string(boot.status, sizeof(boot.status)));
    138   ASSERT_EQ(std::string(sizeof(boot.stage), '\0'), std::string(boot.stage, sizeof(boot.stage)));
    139   ASSERT_EQ(std::string(sizeof(boot.reserved), '\0'),
    140             std::string(boot.reserved, sizeof(boot.reserved)));
    141 }
    142 
    143 TEST_F(BootloaderMessageTest, write_bootloader_message_options_long) {
    144   if (!has_misc) {
    145     GTEST_LOG_(INFO) << "Test skipped due to no /misc partition found on the device.";
    146     return;
    147   }
    148 
    149   // Write super long message.
    150   std::vector<std::string> options;
    151   for (int i = 0; i < 100; i++) {
    152     options.push_back("option: " + std::to_string(i));
    153   }
    154 
    155   std::string err;
    156   ASSERT_TRUE(write_bootloader_message(options, &err)) << "Failed to write BCB: " << err;
    157 
    158   // Read and verify.
    159   bootloader_message boot;
    160   ASSERT_TRUE(read_bootloader_message(&boot, &err)) << "Failed to read BCB: " << err;
    161 
    162   // Make sure it's long enough.
    163   std::string expected = "recovery\n" + android::base::Join(options, "\n") + "\n";
    164   ASSERT_GE(expected.size(), sizeof(boot.recovery));
    165 
    166   // command and recovery fields should be set.
    167   ASSERT_EQ("boot-recovery", std::string(boot.command));
    168   ASSERT_EQ(expected.substr(0, sizeof(boot.recovery) - 1), std::string(boot.recovery));
    169   ASSERT_EQ('\0', boot.recovery[sizeof(boot.recovery) - 1]);
    170 
    171   // The rest should be cleared.
    172   ASSERT_EQ(std::string(sizeof(boot.status), '\0'), std::string(boot.status, sizeof(boot.status)));
    173   ASSERT_EQ(std::string(sizeof(boot.stage), '\0'), std::string(boot.stage, sizeof(boot.stage)));
    174   ASSERT_EQ(std::string(sizeof(boot.reserved), '\0'),
    175             std::string(boot.reserved, sizeof(boot.reserved)));
    176 }
    177 
    178 TEST_F(BootloaderMessageTest, update_bootloader_message) {
    179   if (!has_misc) {
    180     GTEST_LOG_(INFO) << "Test skipped due to no /misc partition found on the device.";
    181     return;
    182   }
    183 
    184   // Inject some bytes into boot, which should be not overwritten later.
    185   bootloader_message boot;
    186   strlcpy(boot.recovery, "random message", sizeof(boot.recovery));
    187   strlcpy(boot.reserved, "reserved bytes", sizeof(boot.reserved));
    188   std::string err;
    189   ASSERT_TRUE(write_bootloader_message(boot, &err)) << "Failed to write BCB: " << err;
    190 
    191   // Update the BCB message.
    192   std::vector<std::string> options = { "option1", "option2" };
    193   ASSERT_TRUE(update_bootloader_message(options, &err)) << "Failed to update BCB: " << err;
    194 
    195   bootloader_message boot_verify;
    196   ASSERT_TRUE(read_bootloader_message(&boot_verify, &err)) << "Failed to read BCB: " << err;
    197 
    198   // Verify that command and recovery fields should be set.
    199   ASSERT_EQ("boot-recovery", std::string(boot_verify.command));
    200   std::string expected = "recovery\n" + android::base::Join(options, "\n") + "\n";
    201   ASSERT_EQ(expected, std::string(boot_verify.recovery));
    202 
    203   // The rest should be intact.
    204   ASSERT_EQ(std::string(boot.status), std::string(boot_verify.status));
    205   ASSERT_EQ(std::string(boot.stage), std::string(boot_verify.stage));
    206   ASSERT_EQ(std::string(boot.reserved), std::string(boot_verify.reserved));
    207 }
    208