• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright (C) 2019 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 // Code here has been inspired by
17 // https://github.com/u-boot/u-boot/blob/master/tools/mkenvimage.c The bare
18 // minimum amount of functionality for our application is replicated.
19 
20 #include <iostream>
21 
22 #include <zlib.h>
23 
24 #include <android-base/logging.h>
25 #include <android-base/strings.h>
26 #include <gflags/gflags.h>
27 
28 #include "common/libs/fs/shared_buf.h"
29 #include "common/libs/fs/shared_fd.h"
30 #include "common/libs/utils/files.h"
31 #include "common/libs/utils/result.h"
32 
33 #define PAD_VALUE (0xff)
34 #define CRC_SIZE (sizeof(uint32_t))
35 
36 // One NULL needed at the end of the env.
37 #define NULL_PAD_LENGTH (1)
38 
39 DEFINE_uint32(env_size, 4096, "file size of resulting env");
40 DEFINE_string(output_path, "", "output file path");
41 DEFINE_string(input_path, "", "input file path");
42 namespace cuttlefish {
43 namespace {
44 std::string USAGE_MESSAGE =
45     "<flags>\n"
46     "\n"
47     "env_size - length in bytes of the resulting env image. Defaults to 4kb.\n"
48     "input_path - path to input key value mapping as a text file\n"
49     "output_path - path to write resulting environment image including CRC "
50     "to\n";
51 }  // namespace
52 
MkenvimageSlimMain(int argc,char ** argv)53 Result<int> MkenvimageSlimMain(int argc, char** argv) {
54   ::android::base::InitLogging(argv, android::base::StderrLogger);
55   gflags::SetUsageMessage(USAGE_MESSAGE);
56   gflags::ParseCommandLineFlags(&argc, &argv, true);
57   CF_EXPECT(FLAGS_output_path != "", "Output env path isn't defined.");
58   CF_EXPECT(FLAGS_env_size != 0, "env size can't be 0.");
59   CF_EXPECT(!(FLAGS_env_size % 512), "env size must be multiple of 512.");
60 
61   std::string env_readout = ReadFile(FLAGS_input_path);
62   CF_EXPECT(env_readout.length(), "Input env is empty");
63   CF_EXPECT(
64       env_readout.length() <= (FLAGS_env_size - CRC_SIZE - NULL_PAD_LENGTH),
65       "Input env must fit within env_size specified.");
66 
67   std::vector<uint8_t> env_buffer(FLAGS_env_size, PAD_VALUE);
68   uint8_t* env_ptr = env_buffer.data() + CRC_SIZE;
69   memcpy(env_ptr, env_readout.c_str(), FileSize(FLAGS_input_path));
70   env_ptr[env_readout.length()] = 0;  // final byte after the env must be NULL
71   uint32_t crc = crc32(0, env_ptr, FLAGS_env_size - CRC_SIZE);
72   memcpy(env_buffer.data(), &crc, sizeof(uint32_t));
73 
74   auto output_fd =
75       SharedFD::Creat(FLAGS_output_path, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
76   if (!output_fd->IsOpen()) {
77     return CF_ERR("Couldn't open the output file " + FLAGS_output_path);
78   } else if (FLAGS_env_size !=
79              WriteAll(output_fd, (char*)env_buffer.data(), FLAGS_env_size)) {
80     RemoveFile(FLAGS_output_path);
81     return CF_ERR("Couldn't complete write to " + FLAGS_output_path);
82   }
83 
84   return 0;
85 }
86 }  // namespace cuttlefish
87 
main(int argc,char ** argv)88 int main(int argc, char** argv) {
89   auto res = cuttlefish::MkenvimageSlimMain(argc, argv);
90   if (res.ok()) {
91     return *res;
92   }
93   LOG(ERROR) << "mkenvimage_slim failed: \n" << res.error().Message();
94   LOG(ERROR) << "mkenvimage_slim failed: \n" << res.error().Trace();
95   abort();
96 }
97