summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKevin Chavez <kechavez@google.com>2016-08-18 13:59:12 -0400
committerKevin Chavez <kechavez@google.com>2016-08-19 13:33:21 -0400
commitaaad91c96ae5f4c573bbd4361571beb0f8dbd929 (patch)
tree92bc9b427a9f3eec505e8bb0f7275d0dc9e8f9fd
parentd03e02da9ed504950e1145d3941bdcd45c7829ed (diff)
downloadbrillo-aaad91c96ae5f4c573bbd4361571beb0f8dbd929.tar.gz
brillo: Add tool for creating A/B metadata misc images.
This tool creates a misc image containing the A/B metadata to be used by an A/B aware bootloader. It is to be placed in the "misc" partition of a final disk image. BUG=29072958 TEST=Unit tests covering input of various metadata attribute values. Change-Id: Ic9d8b5813c39556fbc3dedc7325bd90b92bb1ff3
-rw-r--r--brillo_uefi_x86_64/README19
-rw-r--r--brillo_uefi_x86_64/boot_loader/Android.mk3
-rw-r--r--brillo_uefi_x86_64/boot_loader/Makefile1
-rwxr-xr-xbrillo_uefi_x86_64/boot_loader/brillo_boot_loader.efibin59994 -> 61074 bytes
-rw-r--r--brillo_uefi_x86_64/boot_loader/bub_ab_flow.c5
-rw-r--r--brillo_uefi_x86_64/boot_loader/bub_image_util.cc4
-rw-r--r--brillo_uefi_x86_64/boot_loader/bub_util.c53
-rw-r--r--brillo_uefi_x86_64/boot_loader/bub_util.h2
-rw-r--r--brillo_uefi_x86_64/make_misc_image/Android.mk93
-rw-r--r--brillo_uefi_x86_64/make_misc_image/main.cc50
-rw-r--r--brillo_uefi_x86_64/make_misc_image/make_misc_image.cc105
-rw-r--r--brillo_uefi_x86_64/make_misc_image/make_misc_image.h46
-rw-r--r--brillo_uefi_x86_64/make_misc_image/make_misc_image_unittest.cc194
13 files changed, 541 insertions, 34 deletions
diff --git a/brillo_uefi_x86_64/README b/brillo_uefi_x86_64/README
index 30e57df..a6b5e63 100644
--- a/brillo_uefi_x86_64/README
+++ b/brillo_uefi_x86_64/README
@@ -23,6 +23,25 @@ make_efi_image/
NOTE: mtools utility is required on the system in order to create the EFI
image.
+make_misc_image/
+
+ Contains source files for a utility which creates an image to be put into
+ the "misc" partition of the final disk image. This image will contain
+ metadata in binary format to be used for A/B booting. The utility program
+ takes attribute values for two slots, "a" and "b", as well as a path to the
+ output "misc" binary file.
+ Usage:
+ make_misc_image
+ --ab_metadata=a_priority,a_tries_remaining,a_successful_boot,
+ b_priority,b_tries_remaining,b_successful_boot
+ --output=/PATH/TO/MISC_IMAGE
+ Where
+ 0 <= [a,b]_priority <= 15
+ 0 <= [a,b]_tries_remaining <= 7
+ 0 <= [a,b]_successful_boot <= 1
+
+ TODO: Build system integration similar to make_efi_image.
+
-- BUILD SYSTEM INTEGRATION NOTES
If EFI_INPUT_FILE_PATHS is non-empty, the build system system will call the
diff --git a/brillo_uefi_x86_64/boot_loader/Android.mk b/brillo_uefi_x86_64/boot_loader/Android.mk
index 58f4259..197d846 100644
--- a/brillo_uefi_x86_64/boot_loader/Android.mk
+++ b/brillo_uefi_x86_64/boot_loader/Android.mk
@@ -49,7 +49,8 @@ LOCAL_C_INCLUDES :=
LOCAL_SRC_FILES := \
bub_ab_flow.c \
bub_sysdeps_posix.c \
- bub_util.c
+ bub_util.c \
+ bub_crc32.c
include $(BUILD_HOST_STATIC_LIBRARY)
include $(CLEAR_VARS)
diff --git a/brillo_uefi_x86_64/boot_loader/Makefile b/brillo_uefi_x86_64/boot_loader/Makefile
index 8988c2d..e3c316a 100644
--- a/brillo_uefi_x86_64/boot_loader/Makefile
+++ b/brillo_uefi_x86_64/boot_loader/Makefile
@@ -25,6 +25,7 @@ EFI_OBJCOPY = objcopy
EFI_SRC_FILES = bub_ab_flow.c \
bub_boot_kernel.c \
+ bub_crc32.c \
bub_main.c \
bub_ops_uefi.c \
bub_sysdeps_uefi.c \
diff --git a/brillo_uefi_x86_64/boot_loader/brillo_boot_loader.efi b/brillo_uefi_x86_64/boot_loader/brillo_boot_loader.efi
index 7c0f7e8..11173b6 100755
--- a/brillo_uefi_x86_64/boot_loader/brillo_boot_loader.efi
+++ b/brillo_uefi_x86_64/boot_loader/brillo_boot_loader.efi
Binary files differ
diff --git a/brillo_uefi_x86_64/boot_loader/bub_ab_flow.c b/brillo_uefi_x86_64/boot_loader/bub_ab_flow.c
index 799b0c2..7a6df92 100644
--- a/brillo_uefi_x86_64/boot_loader/bub_ab_flow.c
+++ b/brillo_uefi_x86_64/boot_loader/bub_ab_flow.c
@@ -176,7 +176,7 @@ BubAbFlowResult bub_read_ab_data_from_misc(BubOps* ops, BubAbData* data) {
crc = bub_be32toh(data->crc32);
data->crc32 = 0;
- if (crc != bub_crc32((uint8_t *)data, sizeof(BubAbData))) {
+ if (crc != bub_crc32(0, data, sizeof(BubAbData))) {
bub_warning("AB metadata crc is invalid.\n");
return BUB_AB_FLOW_ERROR_INVALID_METADATA;
}
@@ -197,8 +197,7 @@ int bub_write_ab_data_to_misc(BubOps* ops, const BubAbData* data) {
// Calculate crc assign back to crc field, maintaining big endianness.
metadata.crc32 = 0;
- metadata.crc32 = bub_be32toh(bub_crc32((uint8_t*)&metadata,
- sizeof(BubAbData)));
+ metadata.crc32 = bub_be32toh(bub_crc32(0, &metadata, sizeof(BubAbData)));
io_result = ops->write_to_partition(ops,
"misc",
&metadata,
diff --git a/brillo_uefi_x86_64/boot_loader/bub_image_util.cc b/brillo_uefi_x86_64/boot_loader/bub_image_util.cc
index e8e5a15..93358be 100644
--- a/brillo_uefi_x86_64/boot_loader/bub_image_util.cc
+++ b/brillo_uefi_x86_64/boot_loader/bub_image_util.cc
@@ -159,7 +159,7 @@ base::FilePath MyOps::make_metadata_image(const BubAbData* ab_metadata,
ab_metadata_be.crc32 = 0;
ab_metadata_be.crc32 =
- bub_be32toh(bub_crc32((uint8_t*)&ab_metadata_be, sizeof(BubAbData)));
+ bub_be32toh(bub_crc32(0, &ab_metadata_be, sizeof(BubAbData)));
for (size_t n = 0; n < sizeof(BubAbData); n++) {
image[n] = image_data[n];
@@ -206,7 +206,7 @@ int AbTest::CompareMiscImage(BubAbData ab_expected) {
ab_expected_be.crc32 = 0;
ab_expected_be.crc32 =
- bub_be32toh(bub_crc32((uint8_t*)&ab_expected_be, sizeof(BubAbData)));
+ bub_be32toh(bub_crc32(0, &ab_expected_be, sizeof(BubAbData)));
if ((ops_.bub_ops_)->parent.read_from_partition((BubOps *)ops_.bub_ops_,
"misc", ab_actual, 0,
diff --git a/brillo_uefi_x86_64/boot_loader/bub_util.c b/brillo_uefi_x86_64/boot_loader/bub_util.c
index ed1e1f4..923a7c2 100644
--- a/brillo_uefi_x86_64/boot_loader/bub_util.c
+++ b/brillo_uefi_x86_64/boot_loader/bub_util.c
@@ -15,7 +15,6 @@
*/
#include "bub_sysdeps.h"
-#include <stdio.h>
int utf8_to_ucs2(const uint8_t* utf8_data,
size_t utf8_num_bytes,
@@ -59,33 +58,33 @@ void* bub_calloc(size_t size) {
return x;
}
-uint32_t bub_be32toh(uint32_t in) {
- uint8_t* d = (uint8_t*)&in;
- uint32_t ret;
- ret = ((uint32_t)d[0]) << 24;
- ret |= ((uint32_t)d[1]) << 16;
- ret |= ((uint32_t)d[2]) << 8;
- ret |= ((uint32_t)d[3]);
- return ret;
-}
-uint64_t bub_be64toh(uint64_t in) {
- uint8_t* d = (uint8_t*)&in;
- uint64_t ret;
- ret = ((uint64_t)d[0]) << 56;
- ret |= ((uint64_t)d[1]) << 48;
- ret |= ((uint64_t)d[2]) << 40;
- ret |= ((uint64_t)d[3]) << 32;
- ret |= ((uint64_t)d[4]) << 24;
- ret |= ((uint64_t)d[5]) << 16;
- ret |= ((uint64_t)d[6]) << 8;
- ret |= ((uint64_t)d[7]);
- return ret;
-}
+uint32_t bub_be32toh(uint32_t value) {
+ union {
+ uint8_t bytes[4];
+ uint32_t value;
+ } v;
-uint32_t bub_crc32(const uint8_t* data, size_t data_size) {
+ v.bytes[0] = (value>>24) & 0xff;
+ v.bytes[1] = (value>>16) & 0xff;
+ v.bytes[2] = (value>>8) & 0xff;
+ v.bytes[3] = value & 0xff;
+ return v.value;
+}
- /* TODO: Determine crc polynomial and implement here. */
+uint64_t bub_be64toh(uint64_t value) {
+ union {
+ uint8_t bytes[8];
+ uint64_t value;
+ } v;
- return 0;
-} \ No newline at end of file
+ v.bytes[0] = (value>>56) & 0xff;
+ v.bytes[1] = (value>>48) & 0xff;
+ v.bytes[2] = (value>>40) & 0xff;
+ v.bytes[3] = (value>>32) & 0xff;
+ v.bytes[4] = (value>>24) & 0xff;
+ v.bytes[5] = (value>>16) & 0xff;
+ v.bytes[6] = (value>>8) & 0xff;
+ v.bytes[7] = value & 0xff;
+ return v.value;
+}
diff --git a/brillo_uefi_x86_64/boot_loader/bub_util.h b/brillo_uefi_x86_64/boot_loader/bub_util.h
index 74b32f3..a343bd4 100644
--- a/brillo_uefi_x86_64/boot_loader/bub_util.h
+++ b/brillo_uefi_x86_64/boot_loader/bub_util.h
@@ -50,7 +50,7 @@ uint32_t bub_be32toh(uint32_t in);
uint64_t bub_be64toh(uint64_t in);
/* Calculates and returns crc32 value of |data| given byte size, |data_size|. */
-uint32_t bub_crc32(const uint8_t* data, size_t data_size);
+uint32_t bub_crc32(uint32_t crc_in, const void *buf, int size);
#ifdef __cplusplus
}
diff --git a/brillo_uefi_x86_64/make_misc_image/Android.mk b/brillo_uefi_x86_64/make_misc_image/Android.mk
new file mode 100644
index 0000000..f7540ea
--- /dev/null
+++ b/brillo_uefi_x86_64/make_misc_image/Android.mk
@@ -0,0 +1,93 @@
+#
+# Copyright 2016 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+common_cflags := \
+ -D_FILE_OFFSET_BITS=64 \
+ -D_POSIX_C_SOURCE=199309L \
+ -Wa,--noexecstack \
+ -Werror \
+ -Wall \
+ -Wextra \
+ -Wformat=2 \
+ -Wno-psabi \
+ -Wno-unused-parameter \
+ -ffunction-sections \
+ -fstack-protector-strong \
+ -fvisibility=hidden
+common_cppflags := \
+ -Wnon-virtual-dtor \
+ -fno-strict-aliasing
+common_ldflags := \
+ -Wl,--gc-sections
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := libmiscimg_unittest
+LOCAL_MODULE_HOST_OS := linux
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_CLANG := true
+LOCAL_CFLAGS := $(common_cflags)
+LOCAL_CPPFLAGS := $(common_cppflags)
+LOCAL_LDFLAGS := $(common_ldflags)
+LOCAL_C_INCLUDES := \
+ $(LOCAL_PATH)/make_misc_image.h \
+ $(LOCAL_PATH)/../boot_loader/bub_ab_flow.h \
+ $(LOCAL_PATH)/../boot_loader/bub_image_util.h \
+ $(LOCAL_PATH)/../boot_loader/bub_sysdeps.h \
+ $(LOCAL_PATH)/../boot_loader/bub_util.h \
+ external/gtest/include
+LOCAL_STATIC_LIBRARIES := \
+ libmakemisc_host \
+ libgmock_host \
+ libgtest_host
+LOCAL_SHARED_LIBRARIES := \
+ libchrome
+LOCAL_SRC_FILES := \
+ make_misc_image.cc \
+ make_misc_image_unittest.cc \
+ ../boot_loader/bub_image_util.cc
+LOCAL_LDLIBS_linux := -lrt
+include $(BUILD_HOST_NATIVE_TEST)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := make_misc_image
+LOCAL_MODULE_HOST_OS := linux
+LOCAL_IS_HOST_MODULE := true
+LOCAL_MODULE_CLASS := EXECUTABLES
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_CLANG := true
+LOCAL_CFLAGS := $(common_cflags)
+LOCAL_CPPFLAGS := $(common_cppflags)
+LOCAL_LDFLAGS := $(common_ldflags)
+LOCAL_C_INCLUDES := \
+ $(LOCAL_PATH)/make_misc_image.h \
+ $(LOCAL_PATH)/../boot_loader/bub_ab_flow.h \
+ $(LOCAL_PATH)/../boot_loader/bub_image_util.h \
+ $(LOCAL_PATH)/../boot_loader/bub_sysdeps.h \
+ $(LOCAL_PATH)/../boot_loader/bub_util.h
+LOCAL_STATIC_LIBRARIES := \
+ libmakemisc_host \
+ libgmock_host \
+ libgtest_host
+LOCAL_SHARED_LIBRARIES := \
+ libchrome
+LOCAL_SRC_FILES := \
+ main.cc \
+ make_misc_image.cc \
+ ../boot_loader/bub_image_util.cc
+LOCAL_LDLIBS_linux := -lrt
+include $(BUILD_HOST_EXECUTABLE)
diff --git a/brillo_uefi_x86_64/make_misc_image/main.cc b/brillo_uefi_x86_64/make_misc_image/main.cc
new file mode 100644
index 0000000..54bae3e
--- /dev/null
+++ b/brillo_uefi_x86_64/make_misc_image/main.cc
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "make_misc_image.h"
+
+static void print_usage(void) {
+ cerr << "Usage:\n"
+ " make_misc_image\n"
+ " --abmetadata=a_priority,a_tries_remaining,a_successful_boot,\n"
+ " b_priority,b_tries_remaining,b_successful_boot\n"
+ " --output=/PATH/TO/MISC_IMAGE\n\n";
+}
+
+int main(int argc, const char *argv[]) {
+ BubSlotData metadata[2];
+ base::FilePath misc_name;
+
+ if (!parse_command_line_args(argc, argv, metadata, &misc_name)) {
+ print_usage();
+ return 0;
+ }
+
+ if (!make_misc_image(metadata, &misc_name)) {
+ print_usage();
+ return 0;
+ }
+
+ return 1;
+}
diff --git a/brillo_uefi_x86_64/make_misc_image/make_misc_image.cc b/brillo_uefi_x86_64/make_misc_image/make_misc_image.cc
new file mode 100644
index 0000000..7259863
--- /dev/null
+++ b/brillo_uefi_x86_64/make_misc_image/make_misc_image.cc
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "make_misc_image.h"
+#include <base/command_line.h>
+#include "base/strings/string_tokenizer.h"
+#include "base/strings/string_number_conversions.h"
+
+using namespace base;
+
+static int set_slots_from_tokens(StringTokenizer* st,
+ BubSlotData (&metadata)[2]) {
+ int attribute_value;
+
+ for (int i = 0; i < 2; ++i) {
+ if (!st->GetNext()) {
+ cerr << "ERROR: Need exactly 6 ab_metadata attribute values.\n";
+ return 0;
+ } else if (!StringToInt(st->token(), &attribute_value) ||
+ attribute_value < 0 || attribute_value > 15) {
+ cerr << "ERROR: 0 <= [a,b]_priority <= 15\n";
+ return 0;
+ } else metadata[i].priority = (uint8_t)attribute_value;
+
+ if (!st->GetNext()) {
+ cerr << "ERROR: Need exactly 6 ab_metadata attribute values.\n";
+ return 0;
+ } else if (!StringToInt(st->token(), &attribute_value) ||
+ attribute_value < 0 || attribute_value > 7) {
+ cerr << "ERROR: 0 <= [a,b]_tries_remaining <= 7\n";
+ return 0;
+ } else metadata[i].tries_remaining = (uint8_t)attribute_value;
+
+ if (!st->GetNext()) {
+ cerr << "ERROR: Need exactly 6 ab_metadata attribute values.\n";
+ return 0;
+ } else if (!StringToInt(st->token(), &attribute_value) ||
+ attribute_value < 0 || attribute_value > 1) {
+ cerr << "ERROR: 0 <= [a,b]_successful_boot <= 1\n";
+ return 0;
+ } else metadata[i].successful_boot = (uint8_t)attribute_value;
+ }
+
+ return 1;
+}
+
+int parse_command_line_args(int argc, const char *argv[],
+ BubSlotData (&metadata)[2], FilePath* fname) {
+ CommandLine::Reset();
+ CommandLine::Init(argc, argv);
+ CommandLine* command_line = CommandLine::ForCurrentProcess();
+ CommandLine::StringVector args = command_line->GetArgs();
+
+ StringTokenizer
+ data_tokens(command_line->GetSwitchValueASCII("ab_metadata"), ",");
+
+ if (!set_slots_from_tokens(&data_tokens, metadata))
+ return 0;
+
+ *fname = command_line->GetSwitchValuePath("output");
+ if (fname->empty()) {
+ cerr << "ERROR: Specify output as --output=/PATH/TO/MISC_IMAGE\n";
+ return 0;
+ }
+
+ return 1;
+}
+
+int make_misc_image(const BubSlotData (&metadata)[2], const FilePath* fname) {
+ MyOps ops;
+ BubAbData misc_data;
+
+ ops.write_ab_metadata(&misc_data,
+ (uint8_t[4])BUB_BOOT_CTRL_MAGIC,
+ metadata[0].priority,
+ metadata[0].tries_remaining,
+ metadata[0].successful_boot,
+ metadata[1].priority,
+ metadata[1].tries_remaining,
+ metadata[1].successful_boot);
+ ops.make_metadata_image(&misc_data, fname->value().c_str());
+
+ return 1;
+}
diff --git a/brillo_uefi_x86_64/make_misc_image/make_misc_image.h b/brillo_uefi_x86_64/make_misc_image/make_misc_image.h
new file mode 100644
index 0000000..faa68bb
--- /dev/null
+++ b/brillo_uefi_x86_64/make_misc_image/make_misc_image.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+
+#ifndef BUB_MISC_IMAGE_H_
+#define BUB_MISC_IMAGE_H_
+
+#include <fcntl.h>
+#include <gtest/gtest.h>
+#include <base/files/file_util.h>
+
+#include <iostream>
+#include <string>
+#include "../boot_loader/bub_image_util.h"
+
+#define MAX_FILE_NAME_LENGTH 255
+
+using namespace std;
+
+int parse_command_line_args(int argc, const char *argv[],
+ BubSlotData (&metadata)[2], base::FilePath* fname);
+
+int make_misc_image(const BubSlotData (&metadata)[2], const base::FilePath* fname);
+
+#endif /* BUB_MISC_IMAGE_H_ */ \ No newline at end of file
diff --git a/brillo_uefi_x86_64/make_misc_image/make_misc_image_unittest.cc b/brillo_uefi_x86_64/make_misc_image/make_misc_image_unittest.cc
new file mode 100644
index 0000000..021897c
--- /dev/null
+++ b/brillo_uefi_x86_64/make_misc_image/make_misc_image_unittest.cc
@@ -0,0 +1,194 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "make_misc_image.h"
+
+#define test_args(expected_ret, dat) \
+ do { \
+ BubSlotData metadata[2]; \
+ base::FilePath misc_name; \
+ EXPECT_EQ(expected_ret, \
+ parse_command_line_args(3, \
+ (const char *[]){"make_misc_image", dat, "--output=misc.img"}, \
+ metadata, &misc_name)); \
+ } while (0)
+
+
+TEST_F(AbTest, ActiveAndBackup) {
+ // EXPECT_EQ(1, init_misc(15, 0, 1, 14, 0, 1));
+
+ test_args(
+ 1, // Expected return value.
+ "--ab_metadata=15,0,1,9,0,1"); // Metadata arg.
+}
+
+TEST_F(AbTest, TwoUpdating) {
+ test_args(
+ 1, // Expected return value.
+ "--ab_metadata=15,7,0,15,7,0"); // Metadata arg.
+}
+
+TEST_F(AbTest, ActiveAndInvalid) {
+ test_args(
+ 1, // Expected return value.
+ "--ab_metadata=15,0,1,0,0,0"); // Metadata arg.
+}
+
+TEST_F(AbTest, TwoInvalid) {
+ test_args(
+ 1, // Expected return value.
+ "--ab_metadata=0,0,0,0,0,0"); // Metadata arg.
+}
+
+TEST_F(AbTest, BadPriority) {
+ test_args(
+ 0, // Expected return value.
+ "--ab_metadata=20,0,1,14,0,1"); // Metadata arg.
+ test_args(
+ 0, // Expected return value.
+ "--ab_metadata=20,0,1,14,0,1"); // Metadata arg.
+ test_args(
+ 0, // Expected return value.
+ "--ab_metadata=15,0,1,20,0,1"); // Metadata arg.
+ test_args(
+ 0, // Expected return value.
+ "--ab_metadata=20,0,1,20,0,1"); // Metadata arg.
+}
+
+TEST_F(AbTest, BadTriesRemaining) {
+ test_args(
+ 0, // Expected return value.
+ "--ab_metadata=20,0,1,20,0,1"); // Metadata arg.
+
+ test_args(
+ 0, // Expected return value.
+ "--ab_metadata=15,8,1,14,0,1"); // Metadata arg.
+ test_args(
+ 0, // Expected return value.
+ "--ab_metadata=15,0,1,14,8,1"); // Metadata arg.
+ test_args(
+ 0, // Expected return value.
+ "--ab_metadata=15,8,1,14,8,1"); // Metadata arg.
+}
+
+TEST_F(AbTest, BadSuccessfulBoot) {
+ test_args(
+ 0, // Expected return value.
+ "--ab_metadata=15,0,2,14,0,1"); // Metadata arg.
+ test_args(
+ 0, // Expected return value.
+ "--ab_metadata=15,0,1,14,0,2"); // Metadata arg.
+ test_args(
+ 0, // Expected return value.
+ "--ab_metadata=15,0,2,14,0,2"); // Metadata arg.
+}
+
+TEST_F(AbTest, OutOfRangePositiveAttribute) {
+ test_args(
+ 0, // Expected return value.
+ "--ab_metadata=100,0,1,14,0,1"); // Metadata arg.
+ test_args(
+ 0, // Expected return value.
+ "--ab_metadata=15,100,1,14,0,1"); // Metadata arg.
+ test_args(
+ 0, // Expected return value.
+ "--ab_metadata=15,0,100,14,0,1"); // Metadata arg.
+ test_args(
+ 0, // Expected return value.
+ "--ab_metadata=15,0,1,100,0,1"); // Metadata arg.
+ test_args(
+ 0, // Expected return value.
+ "--ab_metadata=15,0,1,14,100,1"); // Metadata arg.
+ test_args(
+ 0, // Expected return value.
+ "--ab_metadata=15,0,1,14,0,100"); // Metadata arg.
+}
+
+TEST_F(AbTest, OutOfRangeNegativeAttribute) {
+ test_args(
+ 0, // Expected return value.
+ "--ab_metadata=-1,0,1,14,0,1"); // Metadata arg.
+ test_args(
+ 0, // Expected return value.
+ "--ab_metadata=15,-1,1,14,0,1"); // Metadata arg.
+ test_args(
+ 0, // Expected return value.
+ "--ab_metadata=15,0,-1,14,0,1"); // Metadata arg.
+ test_args(
+ 0, // Expected return value.
+ "--ab_metadata=15,0,1,-1,0,1"); // Metadata arg.
+ test_args(
+ 0, // Expected return value.
+ "--ab_metadata=15,0,1,14,-1,1"); // Metadata arg.
+ test_args(
+ 0, // Expected return value.
+ "--ab_metadata=15,0,1,14,0,-1"); // Metadata arg.
+}
+
+TEST_F(AbTest, NonNumericAtrribute) {
+ test_args(
+ 0, // Expected return value.
+ "--ab_metadata=1A,0,1,14,0,1"); // Metadata arg.
+ test_args(
+ 0, // Expected return value.
+ "--ab_metadata=15,A1,1,14,0,1"); // Metadata arg.
+ test_args(
+ 0, // Expected return value.
+ "--ab_metadata=15,0,AA,14,0,1"); // Metadata arg.
+ test_args(
+ 0, // Expected return value.
+ "--ab_metadata=15,0,1,a1a,0,1"); // Metadata arg.
+ test_args(
+ 0, // Expected return value.
+ "--ab_metadata=15,0,1,14,3.14,1"); // Metadata arg.
+ test_args(
+ 0, // Expected return value.
+ "--ab_metadata=15,0,1,14,0,.14"); // Metadata arg.
+}
+
+TEST_F(AbTest, MissingAttributes) {
+ test_args(
+ 0, // Expected return value.
+ "--ab_metadata=15,,1,14,0,1"); // Metadata arg.
+ test_args(
+ 0, // Expected return value.
+ "--ab_metadata=15,0,1,14,0"); // Metadata arg.
+}
+
+TEST_F(AbTest, MissingOutput) {
+ BubSlotData metadata[2];
+ base::FilePath misc_name;
+ EXPECT_EQ(0, //Expected return value.
+ parse_command_line_args(2,
+ (const char *[]){"make_misc_image",
+ "--ab_metadata=15,0,1,14,0,1"},
+ metadata, &misc_name));
+ EXPECT_EQ(0, //Expected return value.
+ parse_command_line_args(2,
+ (const char *[]){"make_misc_image",
+ "--ab_metadata=15,0,1,14,0,1",
+ "--out=misc.img"},
+ metadata, &misc_name));
+}
+