grub-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH] Add module for interacting with the android bootloader control b


From: Shea Levy
Subject: [PATCH] Add module for interacting with the android bootloader control block
Date: Sun, 31 Jan 2016 18:01:03 -0500

---
 grub-core/Makefile.core.def     |   5 ++
 grub-core/android/android_bcb.c | 163 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 168 insertions(+)
 create mode 100644 grub-core/android/android_bcb.c

diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
index 0cc40bb..b045ea4 100644
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -2327,3 +2327,8 @@ module = {
   common = loader/i386/xen_file64.c;
   extra_dist = loader/i386/xen_fileXX.c;
 };
+
+module = {
+  name = android_bcb;
+  common = android/android_bcb.c;
+};
diff --git a/grub-core/android/android_bcb.c b/grub-core/android/android_bcb.c
new file mode 100644
index 0000000..db49446
--- /dev/null
+++ b/grub-core/android/android_bcb.c
@@ -0,0 +1,163 @@
+/* android_bcb.c - module for interacting with the android bootloader control 
block */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2016  Free Software Foundation, Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stddef.h>
+
+#include <grub/dl.h>
+#include <grub/env.h>
+#include <grub/disk.h>
+
+GRUB_MOD_LICENSE ("GPLv3+");
+
+/* Definition of struct bootloader message from 
https://android.googlesource.com/platform/bootable/recovery/+/9d72d4175b06a70c64c8867ff65b3c4c2181c9a9/bootloader.h#20
+ * Available under the following copyright and terms:
+ *
+ * Copyright (C) 2008 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.
+ */
+struct bootloader_message
+{
+  char command[32];
+  char status[32];
+  char recovery[768];
+  // The 'recovery' field used to be 1024 bytes.  It has only ever
+  // been used to store the recovery command line, so 768 bytes
+  // should be plenty.  We carve off the last 256 bytes to store the
+  // stage string (for multistage packages) and possible future
+  // expansion.
+  char stage[32];
+  char slot_suffix[32];
+  char reserved[192];
+} GRUB_PACKED;
+
+struct bcb_state
+{
+  grub_disk_t disk;
+  char internal_write;
+  struct bootloader_message msg;
+};
+
+static struct bcb_state state = { 0 };
+
+#define SET_FIELD(field) \
+  state.msg. field[sizeof state.msg. field - 1] = '\0'; \
+  grub_env_set ("android_bcb_" #field, state.msg. field)
+
+static void open_disk (const char *name) {
+  if (state.disk) {
+    grub_disk_close (state.disk);
+  }
+
+  state.disk = grub_disk_open (name);
+  if (state.disk) {
+    grub_err_t err = grub_disk_read (state.disk, 0, 0, sizeof state.msg,
+                                     &state.msg);
+    if (err) {
+      grub_disk_close (state.disk);
+      state.disk = 0;
+    } else {
+      state.internal_write = 1;
+      SET_FIELD (command);
+      SET_FIELD (status);
+      SET_FIELD (recovery);
+      SET_FIELD (stage);
+      SET_FIELD (slot_suffix);
+      state.internal_write = 0;
+    }
+  }
+}
+
+#define MAYBE_UPDATE_FIELD(field) \
+  do { if (!grub_strcmp (var->name, "android_bcb_" #field)) \
+    { \
+      grub_memcpy (state.msg. field, val, sizeof state.msg. field - 1); \
+      state.msg. field[sizeof state.msg. field - 1] = '\0'; \
+      grub_disk_write (state.disk, 0, \
+                       offsetof (struct bootloader_message, field), \
+                       sizeof state.msg. field, state.msg. field); \
+    } } while (0)
+
+static char *handle_write (struct grub_env_var *var,
+                           const char *val)
+{
+  if (!grub_strcmp (var->name, "android_bcb_disk"))
+    {
+      open_disk (val);
+      if (!state.disk)
+        grub_print_error ();
+    }
+  else if (state.disk && !state.internal_write)
+    {
+      MAYBE_UPDATE_FIELD (command);
+      MAYBE_UPDATE_FIELD (status);
+      MAYBE_UPDATE_FIELD (recovery);
+      MAYBE_UPDATE_FIELD (stage);
+      MAYBE_UPDATE_FIELD (slot_suffix);
+    }
+
+  return grub_strdup (val);
+}
+
+GRUB_MOD_INIT(android_bcb)
+{
+  const char *disk = grub_env_get ("android_bcb_disk");
+  if (disk)
+    {
+      open_disk (disk);
+      if (!state.disk)
+        grub_print_error ();
+    }
+
+  if (!grub_register_variable_hook ("android_bcb_disk", 0, handle_write))
+    grub_print_error ();
+  if (grub_register_variable_hook ("android_bcb_command", 0, handle_write))
+    grub_print_error ();
+  if (grub_register_variable_hook ("android_bcb_status", 0, handle_write))
+    grub_print_error ();
+  if (grub_register_variable_hook ("android_bcb_recovery", 0, handle_write))
+    grub_print_error ();
+  if (grub_register_variable_hook ("android_bcb_stage", 0, handle_write))
+    grub_print_error ();
+  if (grub_register_variable_hook ("android_bcb_slot_suffix", 0, handle_write))
+    grub_print_error ();
+}
+
+GRUB_MOD_FINI(android_bcb)
+{
+  grub_register_variable_hook ("android_bcb_disk", 0, 0);
+  grub_register_variable_hook ("android_bcb_command", 0, 0);
+  grub_register_variable_hook ("android_bcb_status", 0, 0);
+  grub_register_variable_hook ("android_bcb_recovery", 0, 0);
+  grub_register_variable_hook ("android_bcb_stage", 0, 0);
+  grub_register_variable_hook ("android_bcb_slot_suffix", 0, 0);
+
+  if (state.disk)
+    grub_disk_close (state.disk);
+}
-- 
2.7.0




reply via email to

[Prev in Thread] Current Thread [Next in Thread]