/* XXX Investigate possibility of in-place decompression to reduce memory * footprint. Or try to uncompress directly to buf if possible. */ static int uncompress_block (struct grub_lzopio *lzopio) { lzo_uint usize = lzopio->block.usize; if (read_block_data (lzopio) < 0) return -1; /* Incompressible data. */ if (lzopio->block.csize == lzopio->block.usize) { lzopio->block.udata = lzopio->block.cdata; lzopio->block.cdata = NULL; } else { lzopio->block.udata = grub_malloc (lzopio->block.usize); if (!lzopio->block.udata) return -1; if (lzo1x_decompress_safe (lzopio->block.cdata, lzopio->block.csize, lzopio->block.udata, &usize, NULL) != LZO_E_OK) return -1; if (lzopio->ucheck_fun) { grub_uint8_t computed_hash[GRUB_CRYPTO_MAX_MDLEN]; if (lzopio->ucheck_fun->mdlen > GRUB_CRYPTO_MAX_MDLEN) return -1; grub_crypto_hash (lzopio->ucheck_fun, computed_hash, lzopio->block.udata, lzopio->block.usize); if (grub_memcmp (computed_hash, &lzopio->block.ucheck, sizeof (lzopio->block.ucheck)) != 0) return -1; } /* Compressed data can be free now. */ grub_free (lzopio->block.cdata); lzopio->block.cdata = NULL; } return 0; }
int i2cdump_main(int argc UNUSED_PARAM, char **argv) { const unsigned opt_f = (1 << 0), opt_y = (1 << 1), opt_r = (1 << 2); const char *const optstr = "fyr:"; int bus_num, bus_addr, mode = I2C_SMBUS_BYTE_DATA, even = 0, pec = 0; unsigned first = 0x00, last = 0xff, opts; int *block = (int *)bb_common_bufsiz1; char *opt_r_str, *dash; int fd, res; opt_complementary = "-2:?3"; /* from 2 to 3 args */ opts = getopt32(argv, optstr, &opt_r_str); argv += optind; bus_num = i2c_bus_lookup(argv[0]); bus_addr = i2c_parse_bus_addr(argv[1]); if (argv[2]) { switch (argv[2][0]) { case 'b': /* Already set. */ break; case 'c': mode = I2C_SMBUS_BYTE; break; case 'w': mode = I2C_SMBUS_WORD_DATA; break; case 'W': mode = I2C_SMBUS_WORD_DATA; even = 1; break; case 's': mode = I2C_SMBUS_BLOCK_DATA; break; case 'i': mode = I2C_SMBUS_I2C_BLOCK_DATA; break; default: bb_error_msg_and_die("invalid mode"); } if (argv[2][1] == 'p') { if (argv[2][0] == 'W' || argv[2][0] == 'i') { bb_error_msg_and_die( "pec not supported for -W and -i"); } else { pec = 1; } } } if (opts & opt_r) { first = strtol(opt_r_str, &dash, 0); if (dash == opt_r_str || *dash != '-' || first > 0xff) bb_error_msg_and_die("invalid range"); last = xstrtou_range(++dash, 0, first, 0xff); /* Range is not available for every mode. */ switch (mode) { case I2C_SMBUS_BYTE: case I2C_SMBUS_BYTE_DATA: break; case I2C_SMBUS_WORD_DATA: if (!even || (!(first % 2) && last % 2)) break; /* Fall through */ default: bb_error_msg_and_die( "range not compatible with selected mode"); } } fd = i2c_dev_open(bus_num); check_read_funcs(fd, mode, -1 /* data_addr */, pec); i2c_set_slave_addr(fd, bus_addr, opts & opt_f); if (pec) i2c_set_pec(fd, 1); if (!(opts & opt_y)) confirm_action(bus_addr, mode, -1 /* data_addr */, pec); /* All but word data. */ if (mode != I2C_SMBUS_WORD_DATA || even) { int blen = 0; if (mode == I2C_SMBUS_BLOCK_DATA || mode == I2C_SMBUS_I2C_BLOCK_DATA) blen = read_block_data(fd, mode, block); if (mode == I2C_SMBUS_BYTE) { res = i2c_smbus_write_byte(fd, first); if (res < 0) bb_perror_msg_and_die("write start address"); } dump_data(fd, mode, first, last, block, blen); } else { dump_word_data(fd, first, last); } return 0; }