• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018 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 "host/commands/assemble_cvd/boot_config.h"
18 
19 #include <fstream>
20 #include <sstream>
21 #include <string>
22 
23 #include <sys/stat.h>
24 
25 #include <android-base/logging.h>
26 #include <android-base/strings.h>
27 #include <gflags/gflags.h>
28 
29 #include "common/libs/utils/environment.h"
30 #include "common/libs/utils/files.h"
31 #include "common/libs/utils/subprocess.h"
32 #include "host/libs/config/cuttlefish_config.h"
33 #include "host/libs/config/kernel_args.h"
34 #include "host/libs/vm_manager/crosvm_manager.h"
35 #include "host/libs/vm_manager/vm_manager.h"
36 
37 using cuttlefish::vm_manager::CrosvmManager;
38 
39 DECLARE_bool(pause_in_bootloader);
40 DECLARE_string(vm_manager);
41 
42 namespace cuttlefish {
43 namespace {
44 
WriteEnvironment(const CuttlefishConfig & config,const std::vector<std::string> & kernel_args,const std::string & env_path)45 size_t WriteEnvironment(const CuttlefishConfig& config,
46                         const std::vector<std::string>& kernel_args,
47                         const std::string& env_path) {
48   std::ostringstream env;
49   env << "bootargs=" << android::base::Join(kernel_args, " ") << '\0';
50   if (!config.boot_slot().empty()) {
51       env << "android_slot_suffix=_" << config.boot_slot() << '\0';
52   }
53 
54   if(FLAGS_pause_in_bootloader) {
55     env << "bootdelay=-1" << '\0';
56   } else {
57     env << "bootdelay=0" << '\0';
58   }
59 
60   // Note that the 0 index points to the GPT table.
61   env << "bootcmd=boot_android virtio 0#misc" << '\0';
62   if (FLAGS_vm_manager == CrosvmManager::name() &&
63       config.target_arch() == Arch::Arm64) {
64     env << "fdtaddr=0x80000000" << '\0';
65   } else {
66     env << "fdtaddr=0x40000000" << '\0';
67   }
68   env << '\0';
69   std::string env_str = env.str();
70   std::ofstream file_out(env_path.c_str(), std::ios::binary);
71   file_out << env_str;
72 
73   if(!file_out.good()) {
74     return 0;
75   }
76 
77   return env_str.length();
78 }
79 
80 }  // namespace
81 
82 
InitBootloaderEnvPartition(const CuttlefishConfig & config,const CuttlefishConfig::InstanceSpecific & instance)83 bool InitBootloaderEnvPartition(const CuttlefishConfig& config,
84                                 const CuttlefishConfig::InstanceSpecific& instance) {
85   auto boot_env_image_path = instance.uboot_env_image_path();
86   auto tmp_boot_env_image_path = boot_env_image_path + ".tmp";
87   auto uboot_env_path = instance.PerInstancePath("mkenvimg_input");
88   auto kernel_args = KernelCommandLineFromConfig(config);
89   if(!WriteEnvironment(config, kernel_args, uboot_env_path)) {
90     LOG(ERROR) << "Unable to write out plaintext env '" << uboot_env_path << ".'";
91     return false;
92   }
93 
94   auto mkimage_path = HostBinaryPath("mkenvimage");
95   Command cmd(mkimage_path);
96   cmd.AddParameter("-s");
97   cmd.AddParameter("4096");
98   cmd.AddParameter("-o");
99   cmd.AddParameter(tmp_boot_env_image_path);
100   cmd.AddParameter(uboot_env_path);
101   int success = cmd.Start().Wait();
102   if (success != 0) {
103     LOG(ERROR) << "Unable to run mkenvimage. Exited with status " << success;
104     return false;
105   }
106 
107   if(!FileExists(boot_env_image_path) || ReadFile(boot_env_image_path) != ReadFile(tmp_boot_env_image_path)) {
108     if(!RenameFile(tmp_boot_env_image_path, boot_env_image_path)) {
109       LOG(ERROR) << "Unable to delete the old env image.";
110       return false;
111     }
112     LOG(DEBUG) << "Updated bootloader environment image.";
113   } else {
114     RemoveFile(tmp_boot_env_image_path);
115   }
116 
117   return true;
118 }
119 
120 } // namespace cuttlefish
121