freemyipod r975 - Code Review

Jump to: navigation, search
Repository:freemyipod
Revision:r974‎ | r975 | r976 >
Date:15:48, 29 April 2017
Author:user890104
Status:new
Tags:
Comment:
Add Linux version of ipodscsi by njsg
Modified paths:
  • /tools/ipodscsi_linux (added) (history)
  • /tools/ipodscsi_linux/main.c (added) (history)

Diff [purge]

Index: tools/ipodscsi_linux/main.c
@@ -0,0 +1,273 @@
 2+//
 3+//
 4+// Copyright 2011 TheSeven
 5+// Copyright 2012 njsg
 6+//
 7+//
 8+// This file is part of emCORE.
 9+//
 10+// emCORE is free software: you can redistribute it and/or
 11+// modify it under the terms of the GNU General Public License as
 12+// published by the Free Software Foundation, either version 2 of the
 13+// License, or (at your option) any later version.
 14+//
 15+// emCORE is distributed in the hope that it will be useful,
 16+// but WITHOUT ANY WARRANTY; without even the implied warranty of
 17+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 18+// See the GNU General Public License for more details.
 19+//
 20+// You should have received a copy of the GNU General Public License along
 21+// with emCORE. If not, see <http://www.gnu.org/licenses/>.
 22+//
 23+//
 24+
 25+#include <string.h>
 26+#include <errno.h>
 27+#include <unistd.h>
 28+#include <fcntl.h>
 29+#include <stdio.h>
 30+#include <sys/ioctl.h>
 31+#include <scsi/sg.h>
 32+#include <stdlib.h>
 33+
 34+#include "version.h"
 35+
 36+#define APPLE_PREFIX 0xc6
 37+#define CMD_PARTITION 0x94
 38+#define CMD_INIT_FIRMWARE 0x90
 39+#define CMD_SEND_FIRMWARE 0x91
 40+
 41+/* Return a file descriptor for the SCSI device, after checking if it
 42+ is really a SCSI-generic device. */
 43+int open_scsi(const char * scsi_device) {
 44+ int version;
 45+ int sg_fd;
 46+
 47+ /* Open SCSI device */
 48+ if ((sg_fd = open(scsi_device, O_RDWR)) < 0) {
 49+ perror("error opening given file name");
 50+ exit(EXIT_FAILURE);
 51+ }
 52+
 53+ /* Request a very simple scsi-generic ioctl(). If this fails, this
 54+ is not a scsi-generic device. */
 55+ if (ioctl(sg_fd, SG_GET_VERSION_NUM, &version) < 0) {
 56+ printf("%s is not a SCSI-generic device.\n", scsi_device);
 57+ exit(EXIT_FAILURE);
 58+ }
 59+
 60+ return sg_fd;
 61+}
 62+
 63+int usage(char const* msg, char const* msgarg, int argc, char const* const* argv)
 64+{
 65+ printf(msg, msgarg);
 66+ printf("\n"
 67+ "\n"
 68+ "Usage: %s <scsi_device> <command> [options...]\n"
 69+ "\n"
 70+ " scsi_device is the path to a device managed by the\n"
 71+ " 'scsi-generic' driver. Those are usually /dev/sgN,\n"
 72+ " where N is the device number.\n"
 73+ "\n"
 74+ "Commands:\n"
 75+ " writefirmware [-p] <firmware.mse>\n"
 76+ " -r: Reboot device\n"
 77+ " -p: Repartition device\n", argv[0]);
 78+ exit(EXIT_SUCCESS);
 79+}
 80+
 81+int main(int argc, char const* const* argv)
 82+{
 83+ unsigned char sense_buffer[32];
 84+ int arg = 1;
 85+ char const* mse_filename = NULL;
 86+ char const* scsi_device = NULL;
 87+ int repartition = 0;
 88+ int reboot = 0;
 89+ int identify = 0;
 90+
 91+ int f; /* Firmware file descriptor */
 92+ unsigned long bytes;
 93+
 94+ printf("iPodSCSI v. " VERSION " r" VERSION_SVN " - Copyright 2011 by Michael Sparmann (TheSeven)\n"
 95+ "This is free software; see the source for copying conditions. There is NO\n"
 96+ "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
 97+ "\n");
 98+
 99+ if (argc < 4) return usage("Not enough arguments specified", NULL, argc, argv);
 100+
 101+ while (arg < argc)
 102+ {
 103+ if (argv[arg][0] == '-')
 104+ {
 105+ if (!strcmp(argv[arg], "-p")) repartition = 1;
 106+ else if (!strcmp(argv[arg], "-r")) reboot = 1;
 107+ else if (!strcmp(argv[arg], "-i")) identify = 1;
 108+ else return usage("Unknown option: %s", argv[arg], argc, argv);
 109+ }
 110+ else {
 111+ if (scsi_device) {
 112+ if (!mse_filename) {
 113+ mse_filename = argv[arg];
 114+ } else {
 115+ return usage("Excessive argument: %s", argv[arg], argc, argv);
 116+ }
 117+ } else {
 118+ scsi_device = argv[arg];
 119+ }
 120+ }
 121+ arg++;
 122+ }
 123+
 124+ int sg_fd = open_scsi (scsi_device);
 125+
 126+ if (!mse_filename) return usage("No MSE file name specified", NULL, argc, argv);
 127+
 128+
 129+ f = open(mse_filename, O_RDONLY);
 130+
 131+ if (f == -1)
 132+ {
 133+ perror("Error while opening MSE file");
 134+ exit(EXIT_FAILURE);
 135+ }
 136+
 137+
 138+ {
 139+ /* Get MSE file size */
 140+ struct stat *f_stat = malloc (sizeof (struct stat));
 141+ unsigned long size;
 142+
 143+ if (fstat (f, f_stat) == -1) {
 144+ perror("Error while getting MSE file size");
 145+ exit(EXIT_FAILURE);
 146+ }
 147+
 148+ bytes = f_stat->st_size;
 149+
 150+ if (bytes & 0xfff) {
 151+ fprintf(stderr, "MSE file size must be a multiple of 4096\n");
 152+ exit (EXIT_FAILURE);
 153+ }
 154+ }
 155+
 156+ int sectors = bytes >> 12;
 157+
 158+ /* Most commands will have the same prefix. */
 159+ unsigned char cmdBlk[] = {APPLE_PREFIX, 0, 0, 0, 0, 0};
 160+
 161+ sg_io_hdr_t io_hdr;
 162+ memset(&io_hdr, 0, sizeof(sg_io_hdr_t));
 163+ io_hdr.interface_id = 'S';
 164+ io_hdr.dxfer_direction = SG_DXFER_NONE;
 165+ io_hdr.dxfer_len = 0;
 166+ io_hdr.dxferp = NULL;
 167+ io_hdr.cmdp = cmdBlk;
 168+ io_hdr.cmd_len = sizeof(cmdBlk);
 169+ io_hdr.mx_sb_len = 0;
 170+ io_hdr.sbp = NULL;
 171+
 172+ if (repartition)
 173+ {
 174+ printf("Repartitioning...");
 175+ int partsize = sectors << 2;
 176+ cmdBlk[1] = CMD_PARTITION;
 177+ cmdBlk[2] = (partsize >> 24) & 0xff,
 178+ cmdBlk[3] = (partsize >> 16) & 0xff,
 179+ cmdBlk[4] = (partsize >> 8) & 0xff,
 180+ cmdBlk[5] = (partsize) & 0xff ;
 181+
 182+ io_hdr.timeout = 60000;
 183+
 184+ if (ioctl(sg_fd, SG_IO, &io_hdr) < 0) {
 185+ perror("iPod repartitioning SG_IO ioctl error");
 186+ exit(EXIT_FAILURE);
 187+ }
 188+ printf(" done\n");
 189+ }
 190+
 191+ cmdBlk[1] = CMD_INIT_FIRMWARE;
 192+ cmdBlk[2] = 0;
 193+ cmdBlk[3] = 0;
 194+ cmdBlk[4] = 0;
 195+ cmdBlk[5] = 0;
 196+
 197+ io_hdr.timeout = 1000;
 198+
 199+ printf("Initiating firmware transfer...");
 200+
 201+ if (ioctl(sg_fd, SG_IO, &io_hdr) < 0) {
 202+ perror("iPod firmware transfer init SG_IO ioctl error");
 203+ exit(EXIT_FAILURE);
 204+ }
 205+ printf(" done\n");
 206+
 207+ printf("Writing firmware...");
 208+
 209+
 210+ cmdBlk[1] = CMD_SEND_FIRMWARE;
 211+
 212+ while (sectors)
 213+ {
 214+ int tsize = sectors > 0x10 ? 0x10 : sectors;
 215+ int got = 0;
 216+
 217+ char * buf = malloc((tsize << 12) * sizeof(char));
 218+
 219+ while (got < (tsize << 12))
 220+ {
 221+ int b = read(f, buf + got, (tsize << 12) - got);
 222+ if (b == -1) {
 223+ perror("Error reading from MSE file");
 224+ exit(EXIT_FAILURE);
 225+ }
 226+ got += b;
 227+ }
 228+
 229+ cmdBlk[3] = tsize;
 230+
 231+ io_hdr.dxfer_direction = SG_DXFER_TO_DEV;
 232+ io_hdr.dxfer_len = tsize << 12;
 233+ io_hdr.dxferp = buf;
 234+ io_hdr.timeout = 5000;
 235+
 236+ if (ioctl(sg_fd, SG_IO, &io_hdr) < 0) {
 237+ perror("iPod firmware transfer SG_IO ioctl error");
 238+ exit(EXIT_FAILURE);
 239+ }
 240+
 241+ sectors -= tsize;
 242+ printf(".");
 243+ fflush(stdout);
 244+ }
 245+ printf(" done\n");
 246+
 247+
 248+ if (reboot)
 249+ {
 250+ printf("Rebooting device...");
 251+
 252+ cmdBlk[0] = 0x1b;
 253+ cmdBlk[1] = 0;
 254+ cmdBlk[2] = 0;
 255+ cmdBlk[3] = 0;
 256+ cmdBlk[4] = 0x02;
 257+ cmdBlk[5] = 0;
 258+
 259+ io_hdr.dxfer_direction = SG_DXFER_NONE;
 260+ io_hdr.dxfer_len = 0;
 261+ io_hdr.dxferp = NULL;
 262+ io_hdr.timeout = 10000;
 263+
 264+ if (ioctl(sg_fd, SG_IO, &io_hdr) < 0) {
 265+ perror("iPod reboot SG_IO ioctl error");
 266+ exit(EXIT_FAILURE);
 267+ }
 268+
 269+ printf(" done\n");
 270+ }
 271+
 272+ close(sg_fd);
 273+ exit(EXIT_SUCCESS);
 274+}