blob: a9a6e76a51a73683aa7d0b1e208f9b1c90f0d95e [file] [log] [blame]
Andrew Geissler84ad7c52020-06-27 00:00:16 -05001/*
2 * Stripe a flash image across multiple files.
3 *
4 * Copyright (C) 2019 Xilinx, Inc. All rights reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in all
14 * copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 */
24
25#include <stdio.h>
26#include <stdlib.h>
27#include <stdint.h>
28#include <stdbool.h>
29#include <unistd.h>
30#include <sys/types.h>
31#include <sys/stat.h>
32#include <fcntl.h>
33#include <string.h>
34
35/* N way (num) in place bit striper. Lay out row wise bits column wise
36 * (from element 0 to N-1). num is the length of x, and dir reverses the
37 * direction of the transform. be determines the bit endianess scheme.
38 * false to lay out bits LSB to MSB (little endian) and true for big endian.
39 *
40 * Best illustrated by examples:
41 * Each digit in the below array is a single bit (num == 3, be == false):
42 *
43 * {{ 76543210, } ----- stripe (dir == false) -----> {{ FCheb630, }
44 * { hgfedcba, } { GDAfc741, }
45 * { HGFEDCBA, }} <---- upstripe (dir == true) ----- { HEBgda52, }}
46 *
47 * Same but with be == true:
48 *
49 * {{ 76543210, } ----- stripe (dir == false) -----> {{ 741gdaFC, }
50 * { hgfedcba, } { 630fcHEB, }
51 * { HGFEDCBA, }} <---- upstripe (dir == true) ----- { 52hebGDA, }}
52 */
53
54static inline void stripe8(uint8_t *x, int num, bool dir, bool be)
55{
56 uint8_t r[num];
57 memset(r, 0, sizeof(uint8_t) * num);
58 int idx[2] = {0, 0};
59 int bit[2] = {0, be ? 7 : 0};
60 int d = dir;
61
62 for (idx[0] = 0; idx[0] < num; ++idx[0]) {
63 for (bit[0] = be ? 7 : 0; bit[0] != (be ? -1 : 8); bit[0] += be ? -1 : 1) {
64 r[idx[!d]] |= x[idx[d]] & 1 << bit[d] ? 1 << bit[!d] : 0;
65 idx[1] = (idx[1] + 1) % num;
66 if (!idx[1]) {
67 bit[1] += be ? -1 : 1;
68 }
69 }
70 }
71 memcpy(x, r, sizeof(uint8_t) * num);
72}
73
74int main (int argc, char *argv []) {
75#ifdef UNSTRIPE
76 bool unstripe = true;
77#else
78 bool unstripe = false;
79#endif
80
81#ifdef FLASH_STRIPE_BE
82 bool be = true;
83#else
84 bool be = false;
85#endif
86
87 int i;
88
89 const char *exe_name = argv[0];
90 argc--;
91 argv++;
92
93 if (argc < 2) {
94 fprintf(stderr, "ERROR: %s requires at least two args\n", exe_name);
95 return 1;
96 }
97
98 const char *single_f = argv[0];
99 int single;
100
101 if (unstripe) {
102 single = creat(single_f, 0644);
103 } else {
104 single = open(single_f, 0);
105 }
106 if (single == -1) {
107 perror(argv[0]);
108 return 1;
109 }
110
111 argv++;
112 argc--;
113
114 int multiple[argc];
115
116 for (i = 0; i < argc; ++i) {
117 if (unstripe) {
118 multiple[i] = open(argv[i], 0);
119 } else {
120 multiple[i] = creat(argv[i], 0644);
121 }
122 if (multiple[i] == -1) {
123 perror(argv[i]);
124 return 1;
125 }
126 }
127
128 while (true) {
129 uint8_t buf[argc];
130 for (i = 0; i < argc; ++i) {
131 switch (read(!unstripe ? single : multiple[
132#if defined(FLASH_STRIPE_BW) && defined (FLASH_STRIPE_BE)
133 argc - 1 -
134#endif
135 i], &buf[i], 1)) {
136 case 0:
137 if (i == 0) {
138 goto done;
139 } else if (!unstripe) {
140 fprintf(stderr, "WARNING:input file %s is not multiple of "
141 "%d bytes, padding with garbage byte\n", single_f,
142 argc);
143 }
144 break;
145 case -1:
146 perror(unstripe ? argv[i] : single_f);
147 return 1;
148 }
149 }
150
151#ifndef FLASH_STRIPE_BW
152 stripe8(buf, argc, unstripe, be);
153#endif
154
155 for (i = 0; i < argc; ++i) {
156 switch (write(unstripe ? single : multiple[
157#if defined(FLASH_STRIPE_BW) && defined (FLASH_STRIPE_BE)
158 argc - 1 -
159#endif
160 i], &buf[i], 1)) {
161 case -1:
162 perror(unstripe ? single_f : argv[i]);
163 return 1;
164 case 0:
165 i--; /* try again */
166 }
167 }
168 }
169
170done:
171 close(single);
172 for (i = 0; i < argc; ++i) {
173 close(multiple[argc]);
174 }
175 return 0;
176}