summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/efi_loader/efi_console.c7
-rw-r--r--lib/fdtdec.c18
-rw-r--r--lib/gunzip.c76
-rw-r--r--lib/string.c31
-rw-r--r--lib/vsprintf.c37
5 files changed, 142 insertions, 27 deletions
diff --git a/lib/efi_loader/efi_console.c b/lib/efi_loader/efi_console.c
index a798d5604a3..8d076058280 100644
--- a/lib/efi_loader/efi_console.c
+++ b/lib/efi_loader/efi_console.c
@@ -9,6 +9,7 @@
#include <ansi.h>
#include <charset.h>
+#include <console.h>
#include <efi_device_path.h>
#include <malloc.h>
#include <time.h>
@@ -299,8 +300,7 @@ static int query_console_serial(int *rows, int *cols)
int n[2];
/* Empty input buffer */
- while (tstc())
- getchar();
+ console_flush_stdin();
/*
* Not all terminals understand CSI [18t for querying the console size.
@@ -960,8 +960,7 @@ static void efi_cin_check(void)
*/
static void efi_cin_empty_buffer(void)
{
- while (tstc())
- getchar();
+ console_flush_stdin();
key_available = false;
}
diff --git a/lib/fdtdec.c b/lib/fdtdec.c
index fb3375ea157..90d34ae105f 100644
--- a/lib/fdtdec.c
+++ b/lib/fdtdec.c
@@ -714,6 +714,24 @@ int fdtdec_get_int_array(const void *blob, int node, const char *prop_name,
return err;
}
+int fdtdec_get_long_array(const void *blob, int node, const char *prop_name,
+ u64 *array, int count)
+{
+ const u64 *cell;
+ int err = 0;
+
+ debug("%s: %s\n", __func__, prop_name);
+ cell = get_prop_check_min_len(blob, node, prop_name,
+ sizeof(u64) * count, &err);
+ if (!err) {
+ int i;
+
+ for (i = 0; i < count; i++)
+ array[i] = fdt64_to_cpu(cell[i]);
+ }
+ return err;
+}
+
int fdtdec_get_int_array_count(const void *blob, int node,
const char *prop_name, u32 *array, int count)
{
diff --git a/lib/gunzip.c b/lib/gunzip.c
index 76f3397fced..20cc14f9688 100644
--- a/lib/gunzip.c
+++ b/lib/gunzip.c
@@ -8,8 +8,10 @@
#include <command.h>
#include <console.h>
#include <div64.h>
+#include <env.h>
#include <gzip.h>
#include <image.h>
+#include <linux/sizes.h>
#include <malloc.h>
#include <memalign.h>
#include <u-boot/crc.h>
@@ -119,7 +121,7 @@ void gzwrite_progress_finish(int returnval,
int gzwrite(unsigned char *src, size_t len, struct blk_desc *dev,
size_t szwritebuf, off_t startoffs, size_t szexpected)
{
- int i, flags;
+ int flags;
z_stream s;
int r = 0;
unsigned char *writebuf;
@@ -127,13 +129,23 @@ int gzwrite(unsigned char *src, size_t len, struct blk_desc *dev,
ulong totalfilled = 0;
lbaint_t blksperbuf, outblock;
u32 expected_crc;
- size_t payload_size;
+ size_t i, payload_size;
+ unsigned long blocks_written;
+ lbaint_t writeblocks;
+ int numfilled = 0;
int iteration = 0;
-
- if (len > 0xffffffff) {
- log_err("Input size over 4 GiB in size not supported\n");
- return -1;
- }
+ /*
+ * Allow runtime configuration of decompression chunk on
+ * sandbox to better cover the chunked decompression
+ * functionality without having to use > 4 GiB files.
+ */
+ const ulong minchunk = 0x400;
+ const ulong maxchunk = SZ_4G - minchunk;
+ const ulong chunk =
+ CONFIG_IS_ENABLED(SANDBOX,
+ (clamp(env_get_ulong("gzwrite_chunk", 10, maxchunk),
+ minchunk, maxchunk)),
+ (maxchunk));
if (!szwritebuf ||
(szwritebuf % dev->blksz) ||
@@ -175,7 +187,7 @@ int gzwrite(unsigned char *src, size_t len, struct blk_desc *dev,
return -1;
}
- payload_size = len - i - 8;
+ payload_size = len - i;
memcpy(&expected_crc, src + len - 8, sizeof(expected_crc));
expected_crc = le32_to_cpu(expected_crc);
@@ -205,35 +217,44 @@ int gzwrite(unsigned char *src, size_t len, struct blk_desc *dev,
return -1;
}
- s.next_in = src + i;
- s.avail_in = payload_size+8;
+ src += i;
+ s.avail_in = 0;
writebuf = (unsigned char *)malloc_cache_aligned(szwritebuf);
/* decompress until deflate stream ends or end of file */
do {
if (s.avail_in == 0) {
- printf("%s: weird termination with result %d\n",
- __func__, r);
- break;
+ if (payload_size == 0) {
+ printf("%s: weird termination with result %d\n",
+ __func__, r);
+ break;
+ }
+
+ s.next_in = src;
+ s.avail_in = (payload_size > chunk) ? chunk : payload_size;
+ src += s.avail_in;
+ payload_size -= s.avail_in;
}
/* run inflate() on input until output buffer not full */
do {
- unsigned long blocks_written;
- int numfilled;
- lbaint_t writeblocks;
-
- s.avail_out = szwritebuf;
- s.next_out = writebuf;
+ if (numfilled) {
+ s.avail_out = szwritebuf - numfilled;
+ s.next_out = writebuf + numfilled;
+ } else {
+ s.avail_out = szwritebuf;
+ s.next_out = writebuf;
+ }
r = inflate(&s, Z_SYNC_FLUSH);
if ((r != Z_OK) &&
(r != Z_STREAM_END)) {
printf("Error: inflate() returned %d\n", r);
goto out;
}
+ crc = crc32(crc, writebuf + numfilled,
+ szwritebuf - s.avail_out - numfilled);
+ totalfilled += szwritebuf - s.avail_out - numfilled;
numfilled = szwritebuf - s.avail_out;
- crc = crc32(crc, writebuf, numfilled);
- totalfilled += numfilled;
if (numfilled < szwritebuf) {
writeblocks = (numfilled+dev->blksz-1)
/ dev->blksz;
@@ -241,14 +262,17 @@ int gzwrite(unsigned char *src, size_t len, struct blk_desc *dev,
dev->blksz-(numfilled%dev->blksz));
} else {
writeblocks = blksperbuf;
+ numfilled = 0;
}
gzwrite_progress(iteration++,
totalfilled,
szexpected);
- blocks_written = blk_dwrite(dev, outblock,
+ if (!numfilled) {
+ blocks_written = blk_dwrite(dev, outblock,
writeblocks, writebuf);
- outblock += blocks_written;
+ outblock += blocks_written;
+ }
if (ctrlc()) {
puts("abort\n");
goto out;
@@ -258,6 +282,12 @@ int gzwrite(unsigned char *src, size_t len, struct blk_desc *dev,
/* done when inflate() says it's done */
} while (r != Z_STREAM_END);
+ if (numfilled) {
+ blocks_written = blk_dwrite(dev, outblock,
+ writeblocks, writebuf);
+ outblock += blocks_written;
+ }
+
if ((szexpected != totalfilled) ||
(crc != expected_crc))
r = -1;
diff --git a/lib/string.c b/lib/string.c
index d56f88d4a84..302efe048b0 100644
--- a/lib/string.c
+++ b/lib/string.c
@@ -379,6 +379,37 @@ char * strndup(const char *s, size_t n)
return new;
}
+
+/**
+ * strdup_const - conditionally duplicate an existing const string
+ * @s: the string to duplicate
+ *
+ * Note: Strings allocated by kstrdup_const should be freed by kfree_const and
+ * must not be passed to krealloc().
+ *
+ * Return: source string if it is in .rodata section otherwise
+ * fallback to kstrdup.
+ */
+const char *strdup_const(const char *s)
+{
+ if (is_kernel_rodata((unsigned long)s))
+ return s;
+
+ return strdup(s);
+}
+
+/**
+ * kfree_const - conditionally free memory
+ * @x: pointer to the memory
+ *
+ * Function calls kfree only if @x is not in .rodata section.
+ */
+void kfree_const(const void *x)
+{
+ if (!is_kernel_rodata((unsigned long)x))
+ free((void *)x);
+}
+
#endif
#ifndef __HAVE_ARCH_STRSPN
diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index c7340a047b2..49dc9c38c65 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -26,6 +26,11 @@
#include <linux/types.h>
#include <linux/string.h>
+/* For %pOF */
+#if CONFIG_IS_ENABLED(OF_CONTROL)
+#include <dm/ofnode.h>
+#endif
+
/* we use this so that we can do without the ctype library */
#define is_digit(c) ((c) >= '0' && (c) <= '9')
@@ -438,6 +443,30 @@ static char *uuid_string(char *buf, char *end, u8 *addr, int field_width,
}
#endif
+#if CONFIG_IS_ENABLED(OF_CONTROL) && !defined(API_BUILD)
+static char *ofnode_string(char *buf, char *end, ofnode *dp, int field_width,
+ int precision, int flags)
+{
+#define NP_PATH_MAX 64
+ char str[NP_PATH_MAX] = { 0 };
+ const char *err = "...";
+
+ /* If dp == NULL output the string '<NULL>' */
+ if (!dp || !ofnode_valid(*dp))
+ return string(buf, end, NULL, field_width, precision, flags);
+
+ /* Get the path and indicate if it got cut off */
+ if (ofnode_get_path(*dp, str, NP_PATH_MAX)) {
+ str[NP_PATH_MAX - 1] = '\0';
+ char *p = str + min((NP_PATH_MAX - 2) - strlen(err), strlen(str));
+ memcpy(p, err, strlen(err) + 1);
+ }
+
+ return string(buf, end, str, field_width, precision, flags);
+#undef NP_PATH_MAX
+}
+#endif
+
/*
* Show a '%p' thing. A kernel extension is that the '%p' is followed
* by an extra set of alphanumeric characters that are extended format
@@ -474,6 +503,14 @@ static char *pointer(const char *fmt, char *buf, char *end, void *ptr,
return device_path_string(buf, end, ptr, field_width,
precision, flags);
#endif
+/* Device paths only exist in the EFI context. */
+#if CONFIG_IS_ENABLED(OF_CONTROL) && !defined(API_BUILD)
+ case 'O':
+ if (fmt[1] == 'F')
+ return ofnode_string(buf, end, ptr, field_width,
+ precision, flags);
+ break;
+#endif
case 'a':
flags |= SPECIAL | ZEROPAD;