From: "Vladimir 'φ-coder/phcoder' Serbinenko" <phcoder@gmail.com>
To: The development of GNU GRUB <grub-devel@gnu.org>
Subject: Re: [PATCH v3 2/3] i386: Add support for loading from android bootimg
Date: Fri, 12 Feb 2016 22:16:39 +0100 [thread overview]
Message-ID: <56BE4BB7.6040203@gmail.com> (raw)
In-Reply-To: <2b7ecf3a0dda2687029878e0e745bd73@shealevy.com>
[-- Attachment #1.1: Type: text/plain, Size: 5034 bytes --]
On 12.02.2016 20:34, Shea Levy wrote:
> OK. Do you have any thoughts on how best to extract the "load the kernel
> and set the command line to a specific string" functionality out of the
> linux command, then?
>
At first I wanted to write a short skeleton patch to show what I meant
but once skeleton is done, there is little actual code involved. Please
try attached patch
> On 2016-02-12 14:22, Vladimir 'phcoder' Serbinenko wrote:
>> Separate command is better as it keeps interface tidy and unpoluted,
>> decreasing maintenance cost. Correct me if I'm wrong but it should be
>> clear from context of file is Android image or usual linux one?
>>
>> Le ven. 12 févr. 2016 20:19, Shea Levy <shea@shealevy.com> a écrit :
>>
>>> On 2016-02-12 12:50, Vladimir 'φ-coder/phcoder' Serbinenko wrote:
>>> > On 08.02.2016 21:47, Shea Levy wrote:
>>> >> ---
>>> >> grub-core/loader/i386/linux.c | 27 +++++++++++++++++++++------
>>> >> 1 file changed, 21 insertions(+), 6 deletions(-)
>>> >>
>>> >> diff --git a/grub-core/loader/i386/linux.c
>>> >> b/grub-core/loader/i386/linux.c
>>> >> index fddcc46..6ab8d3c 100644
>>> >> --- a/grub-core/loader/i386/linux.c
>>> >> +++ b/grub-core/loader/i386/linux.c
>>> >> @@ -35,6 +35,7 @@
>>> >> #include <grub/i18n.h>
>>> >> #include <grub/lib/cmdline.h>
>>> >> #include <grub/linux.h>
>>> >> +#include <grub/android_bootimg.h>
>>> >>
>>> >> GRUB_MOD_LICENSE ("GPLv3+");
>>> >>
>>> >> @@ -695,7 +696,13 @@ grub_cmd_linux (grub_command_t cmd
>>> >> __attribute__ ((unused)),
>>> >> goto fail;
>>> >> }
>>> >>
>>> >> - file = grub_file_open (argv[0]);
>>> >> + char android_cmdline[BOOT_ARGS_SIZE];
>>> >> + android_cmdline[0] = '';
>>> >> + if (grub_memcmp (argv[0], "android_bootimg:", sizeof
>>> >> "android_bootimg:" - 1) == 0)
>>> >> + grub_android_bootimg_load_kernel (argv[0] + sizeof
>>> >> "android_bootimg:" - 1,
>>> >> + &file, android_cmdline);
>>> >> + else
>>> >> + file = grub_file_open (argv[0]);
>>> > I hoped more for autodetection. This gets a bit hairy and proper
>>> > separation is better. Sorry for confusion. I think it's simpler with
>>> > commands like
>>> > android_bootimg [--no-cmdline] [--no-initrd] IMAGE [EXTRA_ARGUMENTS]
>>> > by default it will load both IMAGE, with cmdline and initrd. With
>>> > --no-initrd you can use initrd for custom initrd.
>>>
>>> Autodetection would be possible actually, I didn't think of that. If
>>> grub_file_open fails, we can try grub_android_bootimg_load_kernel on the
>>> same file. Would that be preferable or do we still want a separate
>>> command?
>>>
>>> >
>>> >> if (! file)
>>> >> goto fail;
>>> >>
>>> >> @@ -1008,12 +1015,20 @@ grub_cmd_linux (grub_command_t cmd
>>> >> __attribute__ ((unused)),
>>> >> linux_cmdline = grub_zalloc (maximal_cmdline_size + 1);
>>> >> if (!linux_cmdline)
>>> >> goto fail;
>>> >> - grub_memcpy (linux_cmdline, LINUX_IMAGE, sizeof (LINUX_IMAGE));
>>> >> + grub_size_t cmdline_offset = 0;
>>> >> + if (android_cmdline[0])
>>> >> + {
>>> >> + cmdline_offset = grub_strlen (android_cmdline) + 1;
>>> >> + grub_memcpy (linux_cmdline, android_cmdline, cmdline_offset -
>>> >> 1);
>>> >> + linux_cmdline[cmdline_offset - 1] = ' ';
>>> >> + }
>>> >> + grub_memcpy (linux_cmdline + cmdline_offset, LINUX_IMAGE, sizeof
>>> >> (LINUX_IMAGE));
>>> >> + cmdline_offset += sizeof LINUX_IMAGE - 1;
>>> > LINUX_IMAGE must be at the beginning. don't forget brackets around
>>> > sizeof.
>>> >> grub_create_loader_cmdline (argc, argv,
>>> >> - linux_cmdline
>>> >> - + sizeof (LINUX_IMAGE) - 1,
>>> >> - maximal_cmdline_size
>>> >> - - (sizeof (LINUX_IMAGE) - 1));
>>> >> + linux_cmdline
>>> >> + + cmdline_offset,
>>> >> + maximal_cmdline_size
>>> >> + - cmdline_offset);
>>> >>
>>> >> len = prot_file_size;
>>> >> if (grub_file_read (file, prot_mode_mem, len) != len &&
>>> >> !grub_errno)
>>> >>
>>> >
>>> >
>>> >
>>> > _______________________________________________
>>> > Grub-devel mailing list
>>> > Grub-devel@gnu.org
>>> > https://lists.gnu.org/mailman/listinfo/grub-devel [1]
>>>
>>> _______________________________________________
>>> Grub-devel mailing list
>>> Grub-devel@gnu.org
>>> https://lists.gnu.org/mailman/listinfo/grub-devel [1]
>>
>>
>> Links:
>> ------
>> [1] https://lists.gnu.org/mailman/listinfo/grub-devel
>>
>> _______________________________________________
>> Grub-devel mailing list
>> Grub-devel@gnu.org
>> https://lists.gnu.org/mailman/listinfo/grub-devel
>
>
> _______________________________________________
> Grub-devel mailing list
> Grub-devel@gnu.org
> https://lists.gnu.org/mailman/listinfo/grub-devel
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1.2: android.diff --]
[-- Type: text/x-diff; name="android.diff", Size: 15380 bytes --]
diff --git a/grub-core/loader/i386/linux.c b/grub-core/loader/i386/linux.c
index fddcc46..d3870ae 100644
--- a/grub-core/loader/i386/linux.c
+++ b/grub-core/loader/i386/linux.c
@@ -35,6 +35,7 @@
#include <grub/i18n.h>
#include <grub/lib/cmdline.h>
#include <grub/linux.h>
+#include <grub/android.h>
GRUB_MOD_LICENSE ("GPLv3+");
@@ -673,11 +674,11 @@ grub_linux_unload (void)
return GRUB_ERR_NONE;
}
+
static grub_err_t
-grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
- int argc, char *argv[])
+linux_load (grub_file_t file, grub_off_t fileoffset, grub_off_t filesize,
+ const char *extra_cmdline, int argc, char *argv[])
{
- grub_file_t file = 0;
struct linux_kernel_header lh;
grub_uint8_t setup_sects;
grub_size_t real_size, prot_size, prot_file_size;
@@ -689,15 +690,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
grub_dl_ref (my_mod);
- if (argc == 0)
- {
- grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
- goto fail;
- }
-
- file = grub_file_open (argv[0]);
- if (! file)
- goto fail;
+ grub_file_seek (file, fileoffset);
if (grub_file_read (file, &lh, sizeof (lh)) != sizeof (lh))
{
@@ -757,7 +750,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
setup_sects = GRUB_LINUX_DEFAULT_SETUP_SECTS;
real_size = setup_sects << GRUB_DISK_SECTOR_BITS;
- prot_file_size = grub_file_size (file) - real_size - GRUB_DISK_SECTOR_SIZE;
+ prot_file_size = filesize - real_size - GRUB_DISK_SECTOR_SIZE;
if (grub_le_to_cpu16 (lh.version) >= 0x205
&& lh.kernel_alignment != 0
@@ -871,7 +864,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
/* The other parameters are filled when booting. */
- grub_file_seek (file, real_size + GRUB_DISK_SECTOR_SIZE);
+ grub_file_seek (file, fileoffset + real_size + GRUB_DISK_SECTOR_SIZE);
grub_dprintf ("linux", "bzImage, setup=0x%x, size=0x%x\n",
(unsigned) real_size, (unsigned) prot_size);
@@ -1008,12 +1001,32 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
linux_cmdline = grub_zalloc (maximal_cmdline_size + 1);
if (!linux_cmdline)
goto fail;
- grub_memcpy (linux_cmdline, LINUX_IMAGE, sizeof (LINUX_IMAGE));
- grub_create_loader_cmdline (argc, argv,
- linux_cmdline
- + sizeof (LINUX_IMAGE) - 1,
- maximal_cmdline_size
- - (sizeof (LINUX_IMAGE) - 1));
+ char *cmdline_ptr = linux_cmdline;
+ char *cmdline_ptr_end = linux_cmdline + maximal_cmdline_size;
+ /* Construct BOOT_IMAGE=/boot/... */
+ cmdline_ptr = grub_stpcpy (cmdline_ptr, LINUX_IMAGE);
+ grub_create_loader_cmdline (1, argv, cmdline_ptr,
+ cmdline_ptr_end - cmdline_ptr);
+ cmdline_ptr += grub_strlen (cmdline_ptr);
+ /* Extra */
+ if (cmdline_ptr < cmdline_ptr_end - 1 && *extra_cmdline)
+ {
+ *cmdline_ptr++ = ' ';
+ cmdline_ptr = grub_stpncpy (cmdline_ptr, extra_cmdline,
+ cmdline_ptr_end - cmdline_ptr);
+ }
+
+ /* Rest of command line. */
+ if (cmdline_ptr < cmdline_ptr_end - 1 && argc > 1)
+ {
+ *cmdline_ptr++ = ' ';
+ grub_create_loader_cmdline (argc - 1, argv + 1, cmdline_ptr,
+ cmdline_ptr_end - cmdline_ptr);
+ }
+ else
+ {
+ *cmdline_ptr = '\0';
+ }
len = prot_file_size;
if (grub_file_read (file, prot_mode_mem, len) != len && !grub_errno)
@@ -1029,9 +1042,6 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
fail:
- if (file)
- grub_file_close (file);
-
if (grub_errno != GRUB_ERR_NONE)
{
grub_dl_unref (my_mod);
@@ -1042,31 +1052,32 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
}
static grub_err_t
-grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
- int argc, char *argv[])
+grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+ int argc, char *argv[])
{
- grub_size_t size = 0, aligned_size = 0;
- grub_addr_t addr_min, addr_max;
- grub_addr_t addr;
+ grub_file_t file = 0;
grub_err_t err;
- struct grub_linux_initrd_context initrd_ctx = { 0, 0, 0 };
-
if (argc == 0)
- {
- grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
- goto fail;
- }
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
- if (! loaded)
- {
- grub_error (GRUB_ERR_BAD_ARGUMENT, N_("you need to load the kernel first"));
- goto fail;
- }
+ file = grub_file_open (argv[0]);
+ if (! file)
+ return grub_errno;
- if (grub_initrd_init (argc, argv, &initrd_ctx))
- goto fail;
+ err = linux_load (file, 0, grub_file_size (file), "", argc, argv);
+ grub_file_close (file);
+ return err;
+}
+
+static grub_err_t
+load_initrd (struct grub_linux_initrd_context *initrd_ctx, char *filenames[])
+{
+ grub_size_t size = 0, aligned_size = 0;
+ grub_addr_t addr_min, addr_max;
+ grub_addr_t addr;
+ grub_err_t err;
- size = grub_get_initrd_size (&initrd_ctx);
+ size = grub_get_initrd_size (initrd_ctx);
aligned_size = ALIGN_UP (size, 4096);
/* Get the highest address available for the initrd. */
@@ -1098,10 +1109,7 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
addr = (addr_max - aligned_size) & ~0xFFF;
if (addr < addr_min)
- {
- grub_error (GRUB_ERR_OUT_OF_RANGE, "the initrd is too big");
- goto fail;
- }
+ return grub_error (GRUB_ERR_OUT_OF_RANGE, "the initrd is too big");
{
grub_relocator_chunk_t ch;
@@ -1116,8 +1124,9 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
initrd_mem_target = get_physical_target_address (ch);
}
- if (grub_initrd_load (&initrd_ctx, argv, initrd_mem))
- goto fail;
+ err = grub_initrd_load (initrd_ctx, filenames, initrd_mem);
+ if (err)
+ return err;
grub_dprintf ("linux", "Initrd, addr=0x%x, size=0x%x\n",
(unsigned) addr, (unsigned) size);
@@ -1126,18 +1135,123 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
linux_params.ramdisk_size = size;
linux_params.root_dev = 0x0100; /* XXX */
- fail:
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
+ int argc, char *argv[])
+{
+ struct grub_linux_initrd_context initrd_ctx = { 0, 0, 0 };
+ grub_err_t err;
+
+ if (argc == 0)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
+
+ if (! loaded)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("you need to load the kernel first"));
+
+ err = grub_initrd_init (argc, argv, &initrd_ctx);
+
+ if (!err)
+ err = load_initrd (&initrd_ctx, argv);
+
grub_initrd_close (&initrd_ctx);
+ return err;
+}
+
+static grub_err_t
+grub_cmd_android_bootimg (grub_command_t cmd __attribute__ ((unused)),
+ int argc, char *argv[])
+{
+ grub_file_t file = 0;
+ grub_err_t err = GRUB_ERR_NONE;
+ int do_load_initrd = 1, do_load_cmdline = 1;
+ struct grub_android_boot_img_hdr boot_img_header;
+ char *cmdline = NULL;
+
+ for (; argc > 0; argc--, argv++)
+ {
+ if (grub_strcmp (argv[0], "--no-cmdline") == 0)
+ {
+ do_load_cmdline = 0;
+ continue;
+ }
+ if (grub_strcmp (argv[0], "--no-initrd") == 0)
+ {
+ do_load_initrd = 0;
+ continue;
+ }
+ break;
+ }
+
+ if (argc == 0)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
+
+ file = grub_file_open (argv[0]);
+ if (! file)
+ return grub_errno;
+
+ if (grub_file_read (file, &boot_img_header, sizeof (boot_img_header)) != sizeof (boot_img_header))
+ {
+ if (!grub_errno)
+ grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
+ argv[0]);
+ err = grub_errno;
+ goto fail;
+ }
+
+ if (grub_memcmp (boot_img_header.magic, GRUB_ANDROID_BOOT_MAGIC, GRUB_ANDROID_BOOT_MAGIC_SIZE) != 0)
+ {
+ err = grub_error (GRUB_ERR_BAD_OS, "invalid android magic");
+ goto fail;
+ }
+
+ if (do_load_cmdline)
+ {
+ cmdline = grub_malloc (GRUB_ANDROID_BOOT_EXTRA_ARGS_SIZE
+ + GRUB_ANDROID_BOOT_ARGS_SIZE + 1);
+ if (!cmdline)
+ goto fail;
+ grub_memcpy (cmdline, boot_img_header.cmdline, GRUB_ANDROID_BOOT_ARGS_SIZE);
+ grub_memcpy (cmdline + GRUB_ANDROID_BOOT_ARGS_SIZE, boot_img_header.extra_cmdline, GRUB_ANDROID_BOOT_EXTRA_ARGS_SIZE);
+ cmdline[GRUB_ANDROID_BOOT_EXTRA_ARGS_SIZE + GRUB_ANDROID_BOOT_ARGS_SIZE] = '\0';
+ }
+
+ err = linux_load (file, boot_img_header.page_size, boot_img_header.kernel_size, cmdline ? : "", argc, argv);
+ if (err)
+ goto fail;
+
+ if (do_load_initrd && boot_img_header.ramdisk_size)
+ {
+ struct grub_linux_initrd_component component = {
+ .size = boot_img_header.ramdisk_size,
+ .newc_name = 0,
+ .file = file,
+ .fileoffset = ALIGN_UP (boot_img_header.kernel_size, boot_img_header.page_size)
+ };
+ struct grub_linux_initrd_context initrd_ctx = {
+ .nfiles = 1,
+ .size = boot_img_header.ramdisk_size,
+ .components = &component
+ };
+ err = load_initrd (&initrd_ctx, argv);
+ }
+ fail:
+ grub_file_close (file);
return grub_errno;
}
-static grub_command_t cmd_linux, cmd_initrd;
+
+static grub_command_t cmd_linux, cmd_initrd, cmd_android_bootimg;
GRUB_MOD_INIT(linux)
{
cmd_linux = grub_register_command ("linux", grub_cmd_linux,
0, N_("Load Linux."));
+ cmd_android_bootimg = grub_register_command ("android_bootimg", grub_cmd_android_bootimg,
+ "[--no-initrd] [--no-cmdline] IMAGE [OPTIONS]", N_("Load Android bootimg."));
cmd_initrd = grub_register_command ("initrd", grub_cmd_initrd,
0, N_("Load initrd."));
my_mod = mod;
@@ -1147,4 +1261,5 @@ GRUB_MOD_FINI(linux)
{
grub_unregister_command (cmd_linux);
grub_unregister_command (cmd_initrd);
+ grub_unregister_command (cmd_android_bootimg);
}
diff --git a/grub-core/loader/linux.c b/grub-core/loader/linux.c
index be6fa0f..dea0299 100644
--- a/grub-core/loader/linux.c
+++ b/grub-core/loader/linux.c
@@ -23,13 +23,6 @@ struct newc_head
char check[8];
} GRUB_PACKED;
-struct grub_linux_initrd_component
-{
- grub_file_t file;
- char *newc_name;
- grub_off_t size;
-};
-
struct dir
{
char *name;
@@ -208,6 +201,7 @@ grub_initrd_init (int argc, char *argv[],
initrd_ctx->nfiles++;
initrd_ctx->components[i].size
= grub_file_size (initrd_ctx->components[i].file);
+ initrd_ctx->components[i].fileoffset = 0;
initrd_ctx->size += initrd_ctx->components[i].size;
}
@@ -279,6 +273,8 @@ grub_initrd_load (struct grub_linux_initrd_context *initrd_ctx,
}
cursize = initrd_ctx->components[i].size;
+ grub_file_seek (initrd_ctx->components[i].file,
+ initrd_ctx->components[i].fileoffset);
if (grub_file_read (initrd_ctx->components[i].file, ptr, cursize)
!= cursize)
{
diff --git a/include/grub/android.h b/include/grub/android.h
new file mode 100644
index 0000000..7cd25f4
--- /dev/null
+++ b/include/grub/android.h
@@ -0,0 +1,73 @@
+/* tools/mkbootimg/bootimg.h
+**
+** 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.
+*/
+#ifndef _GRUB_ANDROID_BOOT_IMAGE_H_
+#define _GRUB_ANDROID_BOOT_IMAGE_H_
+
+#include <grub/types.h>
+
+#define GRUB_ANDROID_BOOT_MAGIC "ANDROID!"
+#define GRUB_ANDROID_BOOT_MAGIC_SIZE 8
+#define GRUB_ANDROID_BOOT_NAME_SIZE 16
+#define GRUB_ANDROID_BOOT_ARGS_SIZE 512
+#define GRUB_ANDROID_BOOT_EXTRA_ARGS_SIZE 1024
+struct grub_android_boot_img_hdr
+{
+ grub_uint8_t magic[GRUB_ANDROID_BOOT_MAGIC_SIZE];
+ grub_uint32_t kernel_size; /* size in bytes */
+ grub_uint32_t kernel_addr; /* physical load addr */
+ grub_uint32_t ramdisk_size; /* size in bytes */
+ grub_uint32_t ramdisk_addr; /* physical load addr */
+ grub_uint32_t second_size; /* size in bytes */
+ grub_uint32_t second_addr; /* physical load addr */
+ grub_uint32_t tags_addr; /* physical addr for kernel tags */
+ grub_uint32_t page_size; /* flash page size we assume */
+ grub_uint32_t unused[2]; /* future expansion: should be 0 */
+ grub_uint8_t name[GRUB_ANDROID_BOOT_NAME_SIZE]; /* asciiz product name */
+ grub_uint8_t cmdline[GRUB_ANDROID_BOOT_ARGS_SIZE];
+ grub_uint32_t id[8]; /* timestamp / checksum / sha1 / etc */
+ /* Supplemental command line data; kept here to maintain
+ * binary compatibility with older versions of mkbootimg */
+ grub_uint8_t extra_cmdline[GRUB_ANDROID_BOOT_EXTRA_ARGS_SIZE];
+} __attribute__((packed));
+/*
+** +-----------------+
+** | boot header | 1 page
+** +-----------------+
+** | kernel | n pages
+** +-----------------+
+** | ramdisk | m pages
+** +-----------------+
+** | second stage | o pages
+** +-----------------+
+**
+** n = (kernel_size + page_size - 1) / page_size
+** m = (ramdisk_size + page_size - 1) / page_size
+** o = (second_size + page_size - 1) / page_size
+**
+** 0. all entities are page_size aligned in flash
+** 1. kernel and ramdisk are required (size != 0)
+** 2. second is optional (second_size == 0 -> no second)
+** 3. load each element (kernel, ramdisk, second) at
+** the specified physical address (kernel_addr, etc)
+** 4. prepare tags at tag_addr. kernel_args[] is
+** appended to the kernel commandline in the tags.
+** 5. r0 = 0, r1 = MACHINE_TYPE, r2 = tags_addr
+** 6. if second_size != 0: jump to second_addr
+** else: jump to kernel_addr
+*/
+
+#endif
diff --git a/include/grub/linux.h b/include/grub/linux.h
index 594a3f3..4a99d78 100644
--- a/include/grub/linux.h
+++ b/include/grub/linux.h
@@ -9,6 +9,14 @@ struct grub_linux_initrd_context
grub_size_t size;
};
+struct grub_linux_initrd_component
+{
+ grub_file_t file;
+ char *newc_name;
+ grub_off_t fileoffset;
+ grub_off_t size;
+};
+
grub_err_t
grub_initrd_init (int argc, char *argv[],
struct grub_linux_initrd_context *ctx);
diff --git a/include/grub/misc.h b/include/grub/misc.h
index 2a9f87c..ef9c9b6 100644
--- a/include/grub/misc.h
+++ b/include/grub/misc.h
@@ -64,6 +64,17 @@ grub_stpcpy (char *dest, const char *src)
return d - 1;
}
+static inline char *
+grub_stpncpy (char *dest, const char *src, int c)
+{
+ char *p = dest;
+
+ while ((*p++ = *src++) != '\0' && --c)
+ ;
+
+ return p - 1;
+}
+
/* XXX: If grub_memmove is too slow, we must implement grub_memcpy. */
static inline void *
grub_memcpy (void *dest, const void *src, grub_size_t n)
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 213 bytes --]
next prev parent reply other threads:[~2016-02-12 21:16 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 ` [PATCH v3 1/3] Add helper functions to interact with android bootimg disks Shea Levy
2016-02-12 17:42 ` 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 [this message]
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=56BE4BB7.6040203@gmail.com \
--to=phcoder@gmail.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).