grub-devel.gnu.org archive mirror
 help / color / mirror / Atom feed
From: Shea Levy <shea@shealevy.com>
To: The development of GNU GRUB <grub-devel@gnu.org>
Cc: Shea Levy <shea@shealevy.com>
Subject: [PATCH v3 1/3] Add helper functions to interact with android bootimg disks.
Date: Mon,  8 Feb 2016 15:47:37 -0500	[thread overview]
Message-ID: <1454964459-28213-2-git-send-email-shea@shealevy.com> (raw)
In-Reply-To: <1454964459-28213-1-git-send-email-shea@shealevy.com>

Currently, the kernel, command line, and ramdisk can be extracted.
---
 grub-core/Makefile.core.def        |   1 +
 grub-core/loader/android_bootimg.c | 253 +++++++++++++++++++++++++++++++++++++
 include/grub/android_bootimg.h     |  12 ++
 3 files changed, 266 insertions(+)
 create mode 100644 grub-core/loader/android_bootimg.c
 create mode 100644 include/grub/android_bootimg.h

diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
index 0cc40bb..991adad 100644
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -1669,6 +1669,7 @@ module = {
   arm64 = loader/arm64/linux.c;
   common = loader/linux.c;
   common = lib/cmdline.c;
+  common = loader/android_bootimg.c;
   enable = noemu;
 };
 
diff --git a/grub-core/loader/android_bootimg.c b/grub-core/loader/android_bootimg.c
new file mode 100644
index 0000000..bbee915
--- /dev/null
+++ b/grub-core/loader/android_bootimg.c
@@ -0,0 +1,253 @@
+/* android_bootimg.c - Helpers for interacting with the android bootimg format. */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2016 Free Software Foundation, Inc.
+ *
+ *  This program 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.
+ *
+ *  This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/file.h>
+#include <grub/misc.h>
+#include <grub/android_bootimg.h>
+
+/* from https://android.googlesource.com/platform/system/core/+/506d233e7ac8ca4efa80768153d842c296477f99/mkbootimg/bootimg.h */
+/* From here until the end of struct boot_img_hdr available under the following terms:
+ *
+ * Copyright 2007, 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.
+ */
+#define BOOT_MAGIC	"ANDROID!"
+#define BOOT_MAGIC_SIZE	8
+#define BOOT_NAME_SIZE	16
+#define BOOT_EXTRA_ARGS_SIZE	1024
+
+struct boot_img_hdr
+{
+  grub_uint8_t magic[BOOT_MAGIC_SIZE];
+
+  grub_uint32_t kernel_size;
+  grub_uint32_t kernel_addr;
+
+  grub_uint32_t ramdisk_size;
+  grub_uint32_t ramdisk_addr;
+
+  grub_uint32_t second_size;
+  grub_uint32_t second_addr;
+
+  grub_uint32_t tags_addr;
+  grub_uint32_t page_size;
+  grub_uint32_t unused[2];
+
+  grub_uint8_t name[BOOT_NAME_SIZE];
+
+  grub_uint8_t cmdline[BOOT_ARGS_SIZE];
+
+  grub_uint32_t id[8];
+
+  grub_uint8_t extra_cmdline[BOOT_EXTRA_ARGS_SIZE];
+} GRUB_PACKED;
+
+static grub_err_t
+read_hdr (grub_disk_t disk, struct boot_img_hdr *hd)
+{
+  if (grub_disk_read (disk, 0, 0, sizeof *hd, hd))
+    goto fail;
+
+  if (grub_memcmp (hd->magic, BOOT_MAGIC, BOOT_MAGIC_SIZE))
+    goto fail;
+
+  if (hd->unused[0] || hd->unused[1])
+    goto fail;
+
+  hd->kernel_size = grub_le_to_cpu32 (hd->kernel_size);
+  hd->kernel_addr = grub_le_to_cpu32 (hd->kernel_addr);
+  hd->ramdisk_size = grub_le_to_cpu32 (hd->ramdisk_size);
+  hd->ramdisk_addr = grub_le_to_cpu32 (hd->ramdisk_addr);
+  hd->second_size = grub_le_to_cpu32 (hd->second_size);
+  hd->second_addr = grub_le_to_cpu32 (hd->second_addr);
+  hd->tags_addr = grub_le_to_cpu32 (hd->tags_addr);
+  hd->page_size = grub_le_to_cpu32 (hd->page_size);
+
+  grub_size_t i;
+  for (i = 0; i < sizeof hd->id / sizeof hd->id[0]; ++i)
+    {
+      hd->id[i] = grub_le_to_cpu32 (hd->id[i]);
+    }
+
+  return GRUB_ERR_NONE;
+
+fail:
+  return grub_error (GRUB_ERR_BAD_FS, N_("%s not an android bootimg"),
+                     disk->name);
+}
+
+static grub_ssize_t
+grub_android_bootimg_read (grub_file_t file, char *buf, grub_size_t len)
+{
+  grub_size_t len_left = file->size - file->offset;
+  len = len > len_left ? len_left : len;
+  grub_off_t *begin_offset = file->data;
+  grub_off_t actual_offset = *begin_offset + file->offset;
+  file->device->disk->read_hook = file->read_hook;
+  file->device->disk->read_hook_data = file->read_hook_data;
+  grub_errno = grub_disk_read (file->device->disk, 0, actual_offset, len, buf);
+  file->device->disk->read_hook = 0;
+
+  if (grub_errno)
+    return -1;
+  else
+    return len;
+}
+
+static grub_err_t
+grub_android_bootimg_close (grub_file_t file)
+{
+  grub_free (file->data);
+  return GRUB_ERR_NONE;
+}
+
+static struct grub_fs grub_android_bootimg_fs =
+  {
+    .name = "android_bootimg",
+    .read = grub_android_bootimg_read,
+    .close = grub_android_bootimg_close
+  };
+
+grub_err_t
+grub_android_bootimg_load_kernel (const char *disk_path, grub_file_t *file,
+                                  char *cmdline)
+{
+  grub_err_t ret = GRUB_ERR_NONE;
+  struct grub_file *f = 0;
+  grub_disk_t disk = grub_disk_open (disk_path);
+  if (!disk)
+    goto err;
+
+  struct boot_img_hdr hd;
+  if (read_hdr (disk, &hd))
+    goto err;
+
+  f = grub_zalloc (sizeof *f);
+  if (!f)
+    goto err;
+
+  f->fs = &grub_android_bootimg_fs;
+  f->device = grub_zalloc (sizeof *(f->device));
+  if (!f->device)
+    goto err;
+  f->device->disk = disk;
+
+  f->name = grub_malloc (sizeof "kernel");
+  if (!f->name)
+    goto err;
+  grub_memcpy (f->name, "kernel", sizeof "kernel");
+  grub_off_t *begin_offset = grub_malloc (sizeof *begin_offset);
+  if (!begin_offset)
+    goto err;
+  *begin_offset = hd.page_size;
+  f->data = begin_offset;
+  f->size = hd.kernel_size;
+
+  *file = f;
+  grub_memcpy (cmdline, hd.cmdline, BOOT_ARGS_SIZE);
+
+  return ret;
+
+err:
+  ret = grub_errno;
+  if (disk)
+    grub_disk_close (disk);
+
+  if (f)
+    {
+      grub_free (f->device);
+      grub_free (f->name);
+      grub_free (f);
+    }
+
+  return ret;
+}
+
+grub_err_t
+grub_android_bootimg_load_initrd (const char *disk_path, grub_file_t *file)
+{
+  grub_err_t ret = GRUB_ERR_NONE;
+  struct grub_file *f = 0;
+  grub_disk_t disk = grub_disk_open (disk_path);
+  if (!disk)
+    goto err;
+
+  struct boot_img_hdr hd;
+  if (read_hdr (disk, &hd))
+    goto err;
+
+  if (!hd.ramdisk_size)
+    {
+      grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("no ramdisk in `%s'"), disk_path);
+      goto err;
+    }
+
+  f = grub_zalloc (sizeof *f);
+  if (!f)
+    goto err;
+
+  f->fs = &grub_android_bootimg_fs;
+  f->device = grub_zalloc (sizeof *(f->device));
+  if (!f->device)
+    goto err;
+  f->device->disk = disk;
+
+  f->name = grub_malloc (sizeof "ramdisk");
+  if (!f->name)
+    goto err;
+  grub_memcpy (f->name, "ramdisk", sizeof "ramdisk");
+  grub_off_t *begin_offset = grub_malloc (sizeof *begin_offset);
+  if (!begin_offset)
+    goto err;
+  *begin_offset =
+    hd.page_size * (1 + (hd.kernel_size + hd.page_size - 1) / hd.page_size);
+  f->data = begin_offset;
+  f->size = hd.ramdisk_size;
+
+  *file = f;
+
+  return ret;
+
+err:
+  ret = grub_errno;
+  if (disk)
+    grub_disk_close (disk);
+
+  if (f)
+    {
+      grub_free (f->device);
+
+      grub_free (f->name);
+
+      grub_free (f);
+    }
+
+  return ret;
+}
diff --git a/include/grub/android_bootimg.h b/include/grub/android_bootimg.h
new file mode 100644
index 0000000..ff14df7
--- /dev/null
+++ b/include/grub/android_bootimg.h
@@ -0,0 +1,12 @@
+#include <grub/file.h>
+
+#define BOOT_ARGS_SIZE 512
+
+/* Load a kernel from a bootimg. cmdline must be at least BOOT_ARGS_SIZE */
+grub_err_t
+grub_android_bootimg_load_kernel (const char *disk_path, grub_file_t *file,
+                                  char *cmdline);
+
+/* Load an initrd from a bootimg. */
+grub_err_t
+grub_android_bootimg_load_initrd (const char *disk_path, grub_file_t *file);
-- 
2.7.0



  reply	other threads:[~2016-02-08 20:48 UTC|newest]

Thread overview: 19+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-02-08 20:47 [PATCH v3 0/3] Android bootimg support Shea Levy
2016-02-08 20:47 ` Shea Levy [this message]
2016-02-12 17:42   ` [PATCH v3 1/3] Add helper functions to interact with android bootimg disks Vladimir 'φ-coder/phcoder' Serbinenko
2016-02-12 17:53     ` Vladimir 'φ-coder/phcoder' Serbinenko
2016-02-08 20:47 ` [PATCH v3 2/3] i386: Add support for loading from android bootimg Shea Levy
2016-02-12 17:50   ` Vladimir 'φ-coder/phcoder' Serbinenko
2016-02-12 19:19     ` Shea Levy
2016-02-12 19:22       ` Vladimir 'phcoder' Serbinenko
2016-02-12 19:34         ` Shea Levy
2016-02-12 21:16           ` Vladimir 'φ-coder/phcoder' Serbinenko
2016-02-13 10:32             ` Andrei Borzenkov
2016-02-14 13:21             ` Shea Levy
2016-02-14 13:26               ` Vladimir 'phcoder' Serbinenko
2016-02-14 17:20                 ` Andrei Borzenkov
2016-02-14 20:58                 ` Seth Goldberg
2016-02-15  3:41                   ` Andrei Borzenkov
2016-02-15  4:13                     ` Seth Goldberg
2016-02-15 10:55                     ` Vladimir 'phcoder' Serbinenko
2016-02-08 20:47 ` [PATCH v3 3/3] Add support for loading initrd " Shea Levy

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1454964459-28213-2-git-send-email-shea@shealevy.com \
    --to=shea@shealevy.com \
    --cc=grub-devel@gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).