blob: 27b9cf1e8ba4bb61be5cbb61019b8acf3ee8b9e0 [file] [log] [blame]
Stefan Tauner6ad6e012014-06-12 00:04:32 +00001/*
2 * This file is part of the flashrom project.
3 *
4 * Copyright (C) 2009-2010 Carl-Daniel Hailfinger
5 * Copyright (C) 2013 Stefan Tauner
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
Stefan Tauner6ad6e012014-06-12 00:04:32 +000016 */
17
18#include <ctype.h>
19#include <stdlib.h>
20#include <string.h>
21#include "flash.h"
22
Nico Huber7679b5c2023-04-28 21:48:53 +000023int flashprog_read_chunked(struct flashctx *const flash, uint8_t *dst, unsigned int start, unsigned int len,
24 const unsigned int chunksize, readfunc_t *const read)
25{
26 int ret;
27 size_t to_read;
28 for (; len; len -= to_read, dst += to_read, start += to_read) {
29 to_read = min(chunksize, len);
30 ret = read(flash, dst, start, to_read);
31 if (ret)
32 return ret;
33 flashprog_progress_add(flash, to_read);
34 }
35 return 0;
36}
37
Stefan Tauner6ad6e012014-06-12 00:04:32 +000038/* Returns the minimum number of bits needed to represent the given address.
39 * FIXME: use mind-blowing implementation. */
40uint32_t address_to_bits(uint32_t addr)
41{
42 unsigned int lzb = 0;
Daniel Campello251e3cd2022-03-16 07:05:48 -060043 while (((1u << (31 - lzb)) & ~addr) != 0)
Stefan Tauner6ad6e012014-06-12 00:04:32 +000044 lzb++;
45 return 32 - lzb;
46}
47
Nico Huber519be662018-12-23 20:03:35 +010048unsigned int bitcount(unsigned long a)
Stefan Tauner6ad6e012014-06-12 00:04:32 +000049{
Nico Huber519be662018-12-23 20:03:35 +010050 unsigned int i = 0;
Stefan Tauner6ad6e012014-06-12 00:04:32 +000051 for (; a != 0; a >>= 1)
52 if (a & 1)
53 i++;
54 return i;
55}
56
57int max(int a, int b)
58{
59 return (a > b) ? a : b;
60}
61
62int min(int a, int b)
63{
64 return (a < b) ? a : b;
65}
66
67char *strcat_realloc(char *dest, const char *src)
68{
69 dest = realloc(dest, strlen(dest) + strlen(src) + 1);
70 if (!dest) {
71 msg_gerr("Out of memory!\n");
72 return NULL;
73 }
74 strcat(dest, src);
75 return dest;
76}
77
78void tolower_string(char *str)
79{
80 for (; *str != '\0'; str++)
81 *str = (char)tolower((unsigned char)*str);
82}
83
Marc Schink7ecfe482016-03-17 16:07:23 +010084uint8_t reverse_byte(uint8_t x)
85{
86 x = ((x >> 1) & 0x55) | ((x << 1) & 0xaa);
87 x = ((x >> 2) & 0x33) | ((x << 2) & 0xcc);
88 x = ((x >> 4) & 0x0f) | ((x << 4) & 0xf0);
89
90 return x;
91}
92
93void reverse_bytes(uint8_t *dst, const uint8_t *src, size_t length)
94{
95 size_t i;
96
97 for (i = 0; i < length; i++)
98 dst[i] = reverse_byte(src[i]);
99}
100
Stefan Taunerb41d8472014-11-01 22:56:06 +0000101/* FIXME: Find a better solution for MinGW. Maybe wrap strtok_s (C11) if it becomes available */
102#ifdef __MINGW32__
103char* strtok_r(char *str, const char *delim, char **nextp)
104{
105 if (str == NULL)
106 str = *nextp;
107
108 str += strspn(str, delim); /* Skip leading delimiters */
109 if (*str == '\0')
110 return NULL;
111
112 char *ret = str;
113 str += strcspn(str, delim); /* Find end of token */
114 if (*str != '\0')
115 *str++ = '\0';
116
117 *nextp = str;
118 return ret;
119}
Miklós Márton8900d6c2019-07-30 00:03:22 +0200120
121/* strndup is a POSIX function not present in MinGW */
122char *strndup(const char *src, size_t maxlen)
123{
Xiang Wang5feb8cd2021-01-20 17:31:19 +0800124 char *retbuf;
125 size_t len;
126 for (len = 0; len < maxlen; len++)
127 if (src[len] == '\0')
128 break;
129 if ((retbuf = malloc(1 + len)) != NULL) {
130 memcpy(retbuf, src, len);
131 retbuf[len] = '\0';
Miklós Márton8900d6c2019-07-30 00:03:22 +0200132 }
Xiang Wang5feb8cd2021-01-20 17:31:19 +0800133 return retbuf;
Miklós Márton8900d6c2019-07-30 00:03:22 +0200134}
Stefan Taunerb41d8472014-11-01 22:56:06 +0000135#endif
136
Stefan Taunerdc627932015-01-27 18:07:50 +0000137/* There is no strnlen in DJGPP */
Nico Huber2d625722016-05-03 10:48:02 +0200138#if defined(__DJGPP__) || (!defined(__LIBPAYLOAD__) && !defined(HAVE_STRNLEN))
Stefan Taunerdc627932015-01-27 18:07:50 +0000139size_t strnlen(const char *str, size_t n)
140{
141 size_t i;
142 for (i = 0; i < n && str[i] != '\0'; i++)
143 ;
144 return i;
145}
146#endif