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