freemyipod r914 - Code Review

Jump to: navigation, search
Repository:freemyipod
Revision:r913‎ | r914 | r915 >
Date:13:14, 27 April 2014
Author:user890104
Status:new
Tags:
Comment:
New app: diskmode
Modified paths:
  • /apps/diskmode (added) (history)
  • /apps/diskmode/Makefile (modified) (history)
  • /apps/diskmode/main.c (replaced) (history)

Diff [purge]

Index: apps/diskmode/Makefile
@@ -0,0 +1,120 @@
 2+NAME := diskmode
 3+STACKSIZE := 4096
 4+COMPRESS := true
 5+
 6+EMCOREDIR ?= ../../emcore/trunk/
 7+
 8+ifeq ($(shell uname),WindowsNT)
 9+CCACHE :=
 10+else
 11+CCACHE := $(shell which ccache)
 12+endif
 13+
 14+CROSS ?= arm-elf-eabi-
 15+CC := $(CCACHE) $(CROSS)gcc
 16+AS := $(CROSS)as
 17+LD := $(CROSS)ld
 18+OBJCOPY := $(CROSS)objcopy
 19+ELF2ECA := $(CROSS)elf2emcoreapp
 20+
 21+LIBINCLUDES :=
 22+
 23+CFLAGS += -Os -fno-pie -fno-stack-protector -fomit-frame-pointer -I. -I$(EMCOREDIR)/export $(LIBINCLUDES) -ffunction-sections -fdata-sections -mcpu=arm940t -DARM_ARCH=4 -marm
 24+LDFLAGS += "$(shell $(CC) -print-libgcc-file-name)" --emit-relocs --gc-sections
 25+
 26+preprocess = $(shell $(CC) $(PPCFLAGS) $(2) -E -P -x c $(1) | grep -v "^\#")
 27+preprocesspaths = $(shell $(CC) $(PPCFLAGS) $(2) -E -P -x c $(1) | grep -v "^\#" | sed -e "s:^..*:$(dir $(1))&:" | sed -e "s:^\\./::")
 28+
 29+REVISION := $(shell svnversion .)
 30+REVISIONINT := $(shell echo $(REVISION) | sed -e "s/[^0-9].*$$//")
 31+
 32+HELPERS := build/__emcore_armhelpers.o
 33+
 34+SRC := $(call preprocesspaths,SOURCES,-I. -I..)
 35+OBJ := $(SRC:%.c=build/%.o)
 36+OBJ := $(OBJ:%.S=build/%.o) $(HELPERS)
 37+
 38+all: $(NAME)
 39+
 40+-include $(OBJ:%=%.dep)
 41+
 42+$(NAME): build/$(NAME).emcoreapp
 43+
 44+build/$(NAME).emcoreapp: build/$(NAME).elf
 45+ @echo [EMCAPP] $<
 46+ifeq ($(COMPRESS),true)
 47+ @$(ELF2ECA) -z -s $(STACKSIZE) -o $@ $^
 48+else
 49+ @$(ELF2ECA) -s $(STACKSIZE) -o $@ $^
 50+endif
 51+
 52+build/$(NAME).elf: ls.x $(OBJ)
 53+ @echo [LD] $@
 54+ @$(LD) $(LDFLAGS) -o $@ -T ls.x $(OBJ)
 55+
 56+build/%.o: %.c build/version.h
 57+ @echo [CC] $<
 58+ifeq ($(shell uname),WindowsNT)
 59+ @-if not exist $(subst /,\,$(dir $@)) md $(subst /,\,$(dir $@))
 60+else
 61+ @-mkdir -p $(dir $@)
 62+endif
 63+ @$(CC) -c $(CFLAGS) -o $@ $<
 64+ @$(CC) -MM $(CFLAGS) $< > $@.dep.tmp
 65+ @sed -e "s|.*:|$@:|" < $@.dep.tmp > $@.dep
 66+ifeq ($(shell uname),WindowsNT)
 67+ @sed -e "s/.*://" -e "s/\\$$//" < $@.dep.tmp | fmt -1 | sed -e "s/^ *//" -e "s/$$/:/" >> $@.dep
 68+else
 69+ @sed -e 's/.*://' -e 's/\\$$//' < $@.dep.tmp | fmt -1 | sed -e 's/^ *//' -e 's/$$/:/' >> $@.dep
 70+endif
 71+ @rm -f $@.dep.tmp
 72+
 73+build/%.o: %.S build/version.h
 74+ @echo [CC] $<
 75+ifeq ($(shell uname),WindowsNT)
 76+ @-if not exist $(subst /,\,$(dir $@)) md $(subst /,\,$(dir $@))
 77+else
 78+ @-mkdir -p $(dir $@)
 79+endif
 80+ @$(CC) -c $(CFLAGS) -o $@ $<
 81+ @$(CC) -MM $(CFLAGS) $< > $@.dep.tmp
 82+ @sed -e "s|.*:|$@:|" < $@.dep.tmp > $@.dep
 83+ifeq ($(shell uname),WindowsNT)
 84+ @sed -e "s/.*://" -e "s/\\$$//" < $@.dep.tmp | fmt -1 | sed -e "s/^ *//" -e "s/$$/:/" >> $@.dep
 85+else
 86+ @sed -e 's/.*://' -e 's/\\$$//' < $@.dep.tmp | fmt -1 | sed -e 's/^ *//' -e 's/$$/:/' >> $@.dep
 87+endif
 88+ @rm -f $@.dep.tmp
 89+
 90+build/__emcore_%.o: $(EMCOREDIR)/export/%.c
 91+ @echo [CC] $<
 92+ifeq ($(shell uname),WindowsNT)
 93+ @-if not exist $(subst /,\,$(dir $@)) md $(subst /,\,$(dir $@))
 94+else
 95+ @-mkdir -p $(dir $@)
 96+endif
 97+ @$(CC) -c $(CFLAGS) -o $@ $<
 98+
 99+build/__emcore_%.o: $(EMCOREDIR)/export/%.S
 100+ @echo [CC] $<
 101+ifeq ($(shell uname),WindowsNT)
 102+ @-if not exist $(subst /,\,$(dir $@)) md $(subst /,\,$(dir $@))
 103+else
 104+ @-mkdir -p $(dir $@)
 105+endif
 106+ @$(CC) -c $(CFLAGS) -o $@ $<
 107+
 108+build/version.h: version.h ../../.svn/entries
 109+ @echo [PP] $<
 110+ifeq ($(shell uname),WindowsNT)
 111+ @-if not exist build md build
 112+ @sed -e "s/\$$REVISION\$$/$(REVISION)/" -e "s/\$$REVISIONINT\$$/$(REVISIONINT)/" < $< > $@
 113+else
 114+ @-mkdir -p build
 115+ @sed -e 's/\$$REVISION\$$/$(REVISION)/' -e 's/\$$REVISIONINT\$$/$(REVISIONINT)/' < $< > $@
 116+endif
 117+
 118+clean:
 119+ @rm -rf build
 120+
 121+.PHONY: all clean $(NAME)
Index: apps/diskmode/main.c
@@ -0,0 +1,918 @@
 2+//
 3+//
 4+// Copyright 2013 TheSeven
 5+// Copyright 2014 user890104
 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+
 26+#define LITTLE_ENDIAN
 27+
 28+
 29+#include "emcoreapp.h"
 30+
 31+
 32+#define SCSI_TEST_UNIT_READY 0x00
 33+#define SCSI_INQUIRY 0x12
 34+#define SCSI_MODE_SENSE_6 0x1a
 35+#define SCSI_MODE_SENSE_10 0x5a
 36+#define SCSI_REQUEST_SENSE 0x03
 37+#define SCSI_ALLOW_MEDIUM_REMOVAL 0x1e
 38+#define SCSI_READ_CAPACITY 0x25
 39+#define SCSI_READ_FORMAT_CAPACITY 0x23
 40+#define SCSI_READ_10 0x28
 41+#define SCSI_WRITE_10 0x2a
 42+#define SCSI_START_STOP_UNIT 0x1b
 43+#define SCSI_REPORT_LUNS 0xa0
 44+#define SCSI_WRITE_BUFFER 0x3b
 45+
 46+#define SENSE_NOT_READY 0x02
 47+#define SENSE_MEDIUM_ERROR 0x03
 48+#define SENSE_ILLEGAL_REQUEST 0x05
 49+#define SENSE_UNIT_ATTENTION 0x06
 50+
 51+#define ASC_MEDIUM_NOT_PRESENT 0x3a
 52+#define ASC_INVALID_FIELD_IN_CBD 0x24
 53+#define ASC_LBA_OUT_OF_RANGE 0x21
 54+#define ASC_WRITE_ERROR 0x0C
 55+#define ASC_READ_ERROR 0x11
 56+#define ASC_NOT_READY 0x04
 57+#define ASC_INVALID_COMMAND 0x20
 58+
 59+#define ASCQ_BECOMING_READY 0x01
 60+
 61+#define DIRECT_ACCESS_DEVICE 0x00
 62+#define DEVICE_REMOVABLE 0x80
 63+
 64+#define SCSI_FORMAT_CAPACITY_FORMATTED_MEDIA 0x02000000
 65+
 66+
 67+struct storage_info storage_info;
 68+
 69+enum storage_operation {
 70+ OP_READ,
 71+ OP_WRITE
 72+} pending_op;
 73+
 74+unsigned long pending_op_start;
 75+int pending_op_count;
 76+
 77+struct wakeup pending_op_wakeup;
 78+
 79+static const struct usb_devicedescriptor usb_devicedescriptor =
 80+{
 81+ .bLength = sizeof(struct usb_devicedescriptor),
 82+ .bDescriptorType = USB_DESCRIPTOR_TYPE_DEVICE,
 83+ .bcdUSB = 0x0200,
 84+ .bDeviceClass = 0,
 85+ .bDeviceSubClass = 0,
 86+ .bDeviceProtocol = 0,
 87+ .bMaxPacketSize0 = 64,
 88+ .idVendor = 0xffff,
 89+ .idProduct = 0xe001,
 90+ .bcdDevice = 2,
 91+ .iManufacturer = 1,
 92+ .iProduct = 2,
 93+ .iSerialNumber = 0,
 94+ .bNumConfigurations = 1,
 95+};
 96+
 97+static struct __attribute__((packed)) _usb_config1_descriptors
 98+{
 99+ struct usb_configurationdescriptor c1;
 100+ struct usb_interfacedescriptor c1_i0_a0;
 101+ struct usb_endpointdescriptor c1_i0_a0_e1out;
 102+ struct usb_endpointdescriptor c1_i0_a0_e1in;
 103+} usb_config1_descriptors =
 104+{
 105+ .c1 =
 106+ {
 107+ .bLength = sizeof(struct usb_configurationdescriptor),
 108+ .bDescriptorType = USB_DESCRIPTOR_TYPE_CONFIGURATION,
 109+ .wTotalLength = sizeof(struct _usb_config1_descriptors),
 110+ .bNumInterfaces = 1,
 111+ .bConfigurationValue = 1,
 112+ .iConfiguration = 0,
 113+ .bmAttributes = { .buspowered = 1, .selfpowered = 1 },
 114+ .bMaxPower = 100 / 2,
 115+ },
 116+ .c1_i0_a0 =
 117+ {
 118+ .bLength = sizeof(struct usb_interfacedescriptor),
 119+ .bDescriptorType = USB_DESCRIPTOR_TYPE_INTERFACE,
 120+ .bInterfaceNumber = 0,
 121+ .bAlternateSetting = 0,
 122+ .bNumEndpoints = 2,
 123+ .bInterfaceClass = 0x08,
 124+ .bInterfaceSubClass = 0x06,
 125+ .bInterfaceProtocol = 0x50,
 126+ .iInterface = 0,
 127+ },
 128+ .c1_i0_a0_e1out =
 129+ {
 130+ .bLength = sizeof(struct usb_endpointdescriptor),
 131+ .bDescriptorType = USB_DESCRIPTOR_TYPE_ENDPOINT,
 132+ .bEndpointAddress = { .number = 0, .direction = USB_ENDPOINT_DIRECTION_OUT },
 133+ .bmAttributes = { .type = USB_ENDPOINT_ATTRIBUTE_TYPE_BULK },
 134+ .wMaxPacketSize = 512,
 135+ .bInterval = 1,
 136+ },
 137+ .c1_i0_a0_e1in =
 138+ {
 139+ .bLength = sizeof(struct usb_endpointdescriptor),
 140+ .bDescriptorType = USB_DESCRIPTOR_TYPE_ENDPOINT,
 141+ .bEndpointAddress = { .number = 0, .direction = USB_ENDPOINT_DIRECTION_IN },
 142+ .bmAttributes = { .type = USB_ENDPOINT_ATTRIBUTE_TYPE_BULK },
 143+ .wMaxPacketSize = 512,
 144+ .bInterval = 1,
 145+ },
 146+};
 147+
 148+static const struct usb_stringdescriptor usb_string_language =
 149+{
 150+ .bLength = sizeof(usb_string_language) + sizeof(*usb_string_language.wString),
 151+ .bDescriptorType = USB_DESCRIPTOR_TYPE_STRING,
 152+ .wString = { 0x0409 },
 153+};
 154+
 155+static const struct usb_stringdescriptor usb_string_vendor =
 156+{
 157+ .bLength = sizeof(usb_string_vendor) + sizeof(*usb_string_vendor.wString) * 14,
 158+ .bDescriptorType = USB_DESCRIPTOR_TYPE_STRING,
 159+ .wString = { 'f', 'r', 'e', 'e', 'm', 'y', 'i', 'p', 'o', 'd', '.', 'o', 'r', 'g' },
 160+};
 161+
 162+static const struct usb_stringdescriptor usb_string_product =
 163+{
 164+ .bLength = sizeof(usb_string_product) + sizeof(*usb_string_product.wString) * 16,
 165+ .bDescriptorType = USB_DESCRIPTOR_TYPE_STRING,
 166+ .wString = { 'e', 'm', 'C', 'O', 'R', 'E', ' ', 'D', 'i', 's', 'k', ' ', 'm', 'o', 'd', 'e' },
 167+};
 168+
 169+static const struct usb_stringdescriptor* usb_stringdescriptors[] =
 170+{
 171+ &usb_string_language,
 172+ &usb_string_vendor,
 173+ &usb_string_product,
 174+};
 175+
 176+struct __attribute__((packed,aligned(32))) command_block_wrapper
 177+{
 178+ unsigned int signature;
 179+ unsigned int tag;
 180+ unsigned int data_transfer_length;
 181+ unsigned char flags;
 182+ unsigned char lun;
 183+ unsigned char command_length;
 184+ unsigned char command_block[16];
 185+};
 186+
 187+struct __attribute__((packed)) command_status_wrapper
 188+{
 189+ unsigned int signature;
 190+ unsigned int tag;
 191+ unsigned int data_residue;
 192+ unsigned char status;
 193+};
 194+
 195+struct __attribute__((packed)) inquiry_data
 196+{
 197+ unsigned char DeviceType;
 198+ unsigned char DeviceTypeModifier;
 199+ unsigned char Versions;
 200+ unsigned char Format;
 201+ unsigned char AdditionalLength;
 202+ unsigned char Reserved[2];
 203+ unsigned char Capability;
 204+ char VendorId[8];
 205+ char ProductId[16];
 206+ char ProductRevisionLevel[4];
 207+};
 208+
 209+struct __attribute__((packed)) report_lun_data
 210+{
 211+ unsigned int lun_list_length;
 212+ unsigned int reserved1;
 213+ unsigned char luns[1][8];
 214+};
 215+
 216+struct __attribute__((packed)) sense_data
 217+{
 218+ unsigned char ResponseCode;
 219+ unsigned char Obsolete;
 220+ unsigned char fei_sensekey;
 221+ unsigned int Information;
 222+ unsigned char AdditionalSenseLength;
 223+ unsigned int CommandSpecificInformation;
 224+ unsigned char AdditionalSenseCode;
 225+ unsigned char AdditionalSenseCodeQualifier;
 226+ unsigned char FieldReplaceableUnitCode;
 227+ unsigned char SKSV;
 228+ unsigned short SenseKeySpecific;
 229+};
 230+
 231+struct __attribute__((packed)) mode_sense_bdesc_longlba
 232+{
 233+ unsigned char num_blocks[8];
 234+ unsigned char reserved[4];
 235+ unsigned char block_size[4];
 236+};
 237+
 238+struct __attribute__((packed)) mode_sense_bdesc_shortlba
 239+{
 240+ unsigned char density_code;
 241+ unsigned char num_blocks[3];
 242+ unsigned char reserved;
 243+ unsigned char block_size[3];
 244+};
 245+
 246+struct __attribute__((packed)) mode_sense_data_10
 247+{
 248+ unsigned short mode_data_length;
 249+ unsigned char medium_type;
 250+ unsigned char device_specific;
 251+ unsigned char longlba;
 252+ unsigned char reserved;
 253+ unsigned short block_descriptor_length;
 254+ struct mode_sense_bdesc_longlba block_descriptor;
 255+};
 256+
 257+struct __attribute__((packed)) mode_sense_data_6
 258+{
 259+ unsigned char mode_data_length;
 260+ unsigned char medium_type;
 261+ unsigned char device_specific;
 262+ unsigned char block_descriptor_length;
 263+ struct mode_sense_bdesc_shortlba block_descriptor;
 264+};
 265+
 266+struct __attribute__((packed)) capacity
 267+{
 268+ unsigned int block_count;
 269+ unsigned int block_size;
 270+};
 271+
 272+struct __attribute__((packed)) format_capacity
 273+{
 274+ unsigned int following_length;
 275+ unsigned int block_count;
 276+ unsigned int block_size;
 277+};
 278+
 279+union __attribute__((aligned(32)))
 280+{
 281+ struct inquiry_data inquiry;
 282+ struct capacity capacity_data;
 283+ struct format_capacity format_capacity_data;
 284+ struct sense_data sense_data;
 285+ struct mode_sense_data_6 ms_data_6;
 286+ struct mode_sense_data_10 ms_data_10;
 287+ struct report_lun_data lun_data;
 288+ struct command_status_wrapper csw;
 289+} tb;
 290+
 291+static enum
 292+{
 293+ WAITING_FOR_COMMAND,
 294+ SENDING_BLOCKS,
 295+ SENDING_RESULT,
 296+ SENDING_FAILED_RESULT,
 297+ RECEIVING_BLOCKS,
 298+ WAITING_FOR_CSW_COMPLETION
 299+} state = WAITING_FOR_COMMAND;
 300+
 301+static struct
 302+{
 303+ unsigned int sector;
 304+ unsigned int count;
 305+ unsigned int orig_count;
 306+ unsigned int cur_cmd;
 307+ unsigned int tag;
 308+ unsigned int lun;
 309+ unsigned int last_result;
 310+} cur_cmd;
 311+
 312+static struct
 313+{
 314+ unsigned char sense_key;
 315+ unsigned char information;
 316+ unsigned char asc;
 317+ unsigned char ascq;
 318+} cur_sense_data;
 319+
 320+static union usb_endpoint_number outep = { .number = 0, .direction = USB_ENDPOINT_DIRECTION_OUT };
 321+static union usb_endpoint_number inep = { .number = 0, .direction = USB_ENDPOINT_DIRECTION_IN };
 322+
 323+static struct command_block_wrapper cbw;
 324+static int maxpacket = 512;
 325+static int maxlen;
 326+static int length;
 327+static bool locked;
 328+static const struct usb_instance* usb;
 329+static volatile bool ejected = false;
 330+static uint8_t __attribute__((aligned(32))) storage_buffer[0x10000];
 331+
 332+static void listen()
 333+{
 334+ usb_start_rx(usb, outep, &cbw, sizeof(cbw));
 335+}
 336+
 337+static void send_csw(int status)
 338+{
 339+ tb.csw.signature = 0x53425355;
 340+ tb.csw.tag = cur_cmd.tag;
 341+ tb.csw.data_residue = 0;
 342+ tb.csw.status = status;
 343+
 344+ state = WAITING_FOR_CSW_COMPLETION;
 345+ usb_start_tx(usb, inep, &tb.csw, sizeof(tb.csw));
 346+
 347+ if (!status)
 348+ {
 349+ cur_sense_data.sense_key = 0;
 350+ cur_sense_data.information = 0;
 351+ cur_sense_data.asc = 0;
 352+ cur_sense_data.ascq = 0;
 353+ }
 354+}
 355+
 356+static void receive_block_data(void* data, int size)
 357+{
 358+ length = size;
 359+ usb_start_rx(usb, outep, data, size);
 360+ state = RECEIVING_BLOCKS;
 361+}
 362+
 363+static void send_block_data(void* data, int size)
 364+{
 365+ length = size;
 366+ usb_start_tx(usb, inep, data, size);
 367+ state = SENDING_BLOCKS;
 368+}
 369+
 370+static void send_command_result(void* data, int size)
 371+{
 372+ length = size;
 373+ usb_start_tx(usb, inep, data, size);
 374+ state = SENDING_RESULT;
 375+}
 376+
 377+static void send_command_failed_result()
 378+{
 379+ usb_start_tx(usb, inep, NULL, 0);
 380+ state = SENDING_FAILED_RESULT;
 381+}
 382+
 383+static void send_and_read_next()
 384+{
 385+ if (cur_cmd.last_result)
 386+ {
 387+ send_csw(1);
 388+ cur_sense_data.sense_key = SENSE_MEDIUM_ERROR;
 389+ cur_sense_data.asc = ASC_READ_ERROR;
 390+ cur_sense_data.ascq = 0;
 391+ return;
 392+ }
 393+
 394+ pending_op_start = cur_cmd.sector;
 395+ pending_op_count = cur_cmd.count;
 396+ pending_op = OP_READ;
 397+ wakeup_signal(&pending_op_wakeup);
 398+}
 399+
 400+static void copy_padded(char* dest, char* src, int len)
 401+{
 402+ int i = 0;
 403+ while (src[i] && i < len)
 404+ {
 405+ dest[i] = src[i];
 406+ i++;
 407+ }
 408+ while(i < len) dest[i++] = ' ';
 409+}
 410+
 411+static void fill_inquiry()
 412+{
 413+ memset(&tb.inquiry, 0, sizeof(tb.inquiry));
 414+ copy_padded(tb.inquiry.VendorId, storage_info.vendor, sizeof(tb.inquiry.VendorId));
 415+ copy_padded(tb.inquiry.ProductId, storage_info.product, sizeof(tb.inquiry.ProductId));
 416+ copy_padded(tb.inquiry.ProductRevisionLevel, storage_info.revision, sizeof(tb.inquiry.ProductRevisionLevel));
 417+
 418+ tb.inquiry.DeviceType = DIRECT_ACCESS_DEVICE;
 419+ tb.inquiry.AdditionalLength = 0x1f;
 420+ tb.inquiry.Versions = 4; // SPC-2
 421+ tb.inquiry.Format = 2; // SPC-2/3 inquiry format
 422+ tb.inquiry.DeviceTypeModifier = DEVICE_REMOVABLE;
 423+}
 424+
 425+static void handle_scsi(struct command_block_wrapper* cbw)
 426+{
 427+ unsigned int length = cbw->data_transfer_length;
 428+
 429+ if (cbw->signature != 0x43425355)
 430+ {
 431+ usb_set_stall(usb, outep, true);
 432+ usb_set_stall(usb, inep, true);
 433+ return;
 434+ }
 435+ cur_cmd.tag = cbw->tag;
 436+ cur_cmd.lun = cbw->lun;
 437+ cur_cmd.cur_cmd = cbw->command_block[0];
 438+
 439+ switch (cbw->command_block[0])
 440+ {
 441+ case SCSI_TEST_UNIT_READY:
 442+ if (!ejected) send_csw(0);
 443+ else
 444+ {
 445+ send_csw(1);
 446+ cur_sense_data.sense_key = SENSE_NOT_READY;
 447+ cur_sense_data.asc = ASC_MEDIUM_NOT_PRESENT;
 448+ cur_sense_data.ascq = 0;
 449+ }
 450+ break;
 451+
 452+ case SCSI_REPORT_LUNS:
 453+ {
 454+ memset(&tb.lun_data, 0, sizeof(struct report_lun_data));
 455+ tb.lun_data.lun_list_length = 0x08000000;
 456+ send_command_result(&tb.lun_data, MIN(16, length));
 457+ break;
 458+ }
 459+
 460+ case SCSI_INQUIRY:
 461+ fill_inquiry();
 462+ length = MIN(length, cbw->command_block[4]);
 463+ send_command_result(&tb.inquiry, MIN(sizeof(tb.inquiry), length));
 464+ break;
 465+
 466+ case SCSI_REQUEST_SENSE:
 467+ {
 468+ tb.sense_data.ResponseCode = 0x70;
 469+ tb.sense_data.Obsolete = 0;
 470+ tb.sense_data.fei_sensekey = cur_sense_data.sense_key & 0x0f;
 471+ tb.sense_data.Information = cur_sense_data.information;
 472+ tb.sense_data.AdditionalSenseLength = 10;
 473+ tb.sense_data.CommandSpecificInformation = 0;
 474+ tb.sense_data.AdditionalSenseCode = cur_sense_data.asc;
 475+ tb.sense_data.AdditionalSenseCodeQualifier = cur_sense_data.ascq;
 476+ tb.sense_data.FieldReplaceableUnitCode = 0;
 477+ tb.sense_data.SKSV = 0;
 478+ tb.sense_data.SenseKeySpecific = 0;
 479+ send_command_result(&tb.sense_data, MIN(sizeof(tb.sense_data), length));
 480+ break;
 481+ }
 482+
 483+ case SCSI_MODE_SENSE_10:
 484+ {
 485+ if (ejected)
 486+ {
 487+ send_command_failed_result();
 488+ cur_sense_data.sense_key = SENSE_NOT_READY;
 489+ cur_sense_data.asc = ASC_MEDIUM_NOT_PRESENT;
 490+ cur_sense_data.ascq = 0;
 491+ break;
 492+ }
 493+ unsigned char page_code = cbw->command_block[2] & 0x3f;
 494+ switch (page_code)
 495+ {
 496+ case 0x3f:
 497+ tb.ms_data_10.mode_data_length = htobe16(sizeof(tb.ms_data_10) - 2);
 498+ tb.ms_data_10.medium_type = 0;
 499+ tb.ms_data_10.device_specific = 0;
 500+ tb.ms_data_10.reserved = 0;
 501+ tb.ms_data_10.longlba = 1;
 502+ tb.ms_data_10.block_descriptor_length = htobe16(sizeof(tb.ms_data_10.block_descriptor));
 503+
 504+ memset(tb.ms_data_10.block_descriptor.reserved, 0, 4);
 505+ memset(tb.ms_data_10.block_descriptor.num_blocks, 0, 8);
 506+
 507+ tb.ms_data_10.block_descriptor.num_blocks[4] = (storage_info.num_sectors & 0xff000000) >> 24;
 508+ tb.ms_data_10.block_descriptor.num_blocks[5] = (storage_info.num_sectors & 0x00ff0000) >> 16;
 509+ tb.ms_data_10.block_descriptor.num_blocks[6] = (storage_info.num_sectors & 0x0000ff00) >> 8;
 510+ tb.ms_data_10.block_descriptor.num_blocks[7] = (storage_info.num_sectors & 0x000000ff);
 511+
 512+ tb.ms_data_10.block_descriptor.block_size[0] = (storage_info.sector_size & 0xff000000) >> 24;
 513+ tb.ms_data_10.block_descriptor.block_size[1] = (storage_info.sector_size & 0x00ff0000) >> 16;
 514+ tb.ms_data_10.block_descriptor.block_size[2] = (storage_info.sector_size & 0x0000ff00) >> 8;
 515+ tb.ms_data_10.block_descriptor.block_size[3] = (storage_info.sector_size & 0x000000ff);
 516+ send_command_result(&tb.ms_data_10, MIN(sizeof(tb.ms_data_10), length));
 517+ break;
 518+ default:
 519+ send_command_failed_result();
 520+ cur_sense_data.sense_key = SENSE_ILLEGAL_REQUEST;
 521+ cur_sense_data.asc = ASC_INVALID_FIELD_IN_CBD;
 522+ cur_sense_data.ascq = 0;
 523+ break;
 524+ }
 525+ break;
 526+ }
 527+
 528+ case SCSI_MODE_SENSE_6:
 529+ {
 530+ if (ejected)
 531+ {
 532+ send_command_failed_result();
 533+ cur_sense_data.sense_key = SENSE_NOT_READY;
 534+ cur_sense_data.asc = ASC_MEDIUM_NOT_PRESENT;
 535+ cur_sense_data.ascq = 0;
 536+ break;
 537+ }
 538+ unsigned char page_code = cbw->command_block[2] & 0x3f;
 539+ switch (page_code)
 540+ {
 541+ case 0x3f:
 542+ tb.ms_data_6.mode_data_length = sizeof(tb.ms_data_6) - 1;
 543+ tb.ms_data_6.medium_type = 0;
 544+ tb.ms_data_6.device_specific = 0;
 545+ tb.ms_data_6.block_descriptor_length = sizeof(tb.ms_data_6.block_descriptor);
 546+ tb.ms_data_6.block_descriptor.density_code = 0;
 547+ tb.ms_data_6.block_descriptor.reserved = 0;
 548+ if (storage_info.num_sectors > 0xffffff)
 549+ {
 550+ tb.ms_data_6.block_descriptor.num_blocks[0] = 0xff;
 551+ tb.ms_data_6.block_descriptor.num_blocks[1] = 0xff;
 552+ tb.ms_data_6.block_descriptor.num_blocks[2] = 0xff;
 553+ }
 554+ else
 555+ {
 556+ tb.ms_data_6.block_descriptor.num_blocks[0] = (storage_info.num_sectors & 0xff0000) >> 16;
 557+ tb.ms_data_6.block_descriptor.num_blocks[1] = (storage_info.num_sectors & 0x00ff00) >> 8;
 558+ tb.ms_data_6.block_descriptor.num_blocks[2] = (storage_info.num_sectors & 0x0000ff);
 559+ }
 560+ tb.ms_data_6.block_descriptor.block_size[0] = (storage_info.sector_size & 0xff0000) >> 16;
 561+ tb.ms_data_6.block_descriptor.block_size[1] = (storage_info.sector_size & 0x00ff00) >> 8;
 562+ tb.ms_data_6.block_descriptor.block_size[2] = (storage_info.sector_size & 0x0000ff);
 563+ send_command_result(&tb.ms_data_6, MIN(sizeof(tb.ms_data_6), length));
 564+ break;
 565+ default:
 566+ send_command_failed_result();
 567+ cur_sense_data.sense_key = SENSE_ILLEGAL_REQUEST;
 568+ cur_sense_data.asc = ASC_INVALID_FIELD_IN_CBD;
 569+ cur_sense_data.ascq = 0;
 570+ break;
 571+ }
 572+ break;
 573+ }
 574+
 575+ case SCSI_START_STOP_UNIT:
 576+ if ((cbw->command_block[4] & 0xf3) == 2) ejected = true;
 577+ send_csw(0);
 578+ break;
 579+
 580+ case SCSI_ALLOW_MEDIUM_REMOVAL:
 581+ if ((cbw->command_block[4] & 0x03) == 0) locked = false;
 582+ else locked = true;
 583+ send_csw(0);
 584+ break;
 585+
 586+ case SCSI_READ_FORMAT_CAPACITY:
 587+ {
 588+ if (!ejected)
 589+ {
 590+ tb.format_capacity_data.following_length = 0x08000000;
 591+ tb.format_capacity_data.block_count = htobe32(storage_info.num_sectors - 1);
 592+ tb.format_capacity_data.block_size = htobe32(storage_info.sector_size);
 593+ tb.format_capacity_data.block_size |= htobe32(SCSI_FORMAT_CAPACITY_FORMATTED_MEDIA);
 594+ send_command_result(&tb.format_capacity_data, MIN(sizeof(tb.format_capacity_data), length));
 595+ }
 596+ else
 597+ {
 598+ send_command_failed_result();
 599+ cur_sense_data.sense_key = SENSE_NOT_READY;
 600+ cur_sense_data.asc = ASC_MEDIUM_NOT_PRESENT;
 601+ cur_sense_data.ascq = 0;
 602+ }
 603+ break;
 604+ }
 605+
 606+ case SCSI_READ_CAPACITY:
 607+ {
 608+ if (!ejected)
 609+ {
 610+ tb.capacity_data.block_count = htobe32(storage_info.num_sectors - 1);
 611+ tb.capacity_data.block_size = htobe32(storage_info.sector_size);
 612+ send_command_result(&tb.capacity_data, MIN(sizeof(tb.capacity_data), length));
 613+ }
 614+ else
 615+ {
 616+ send_command_failed_result();
 617+ cur_sense_data.sense_key = SENSE_NOT_READY;
 618+ cur_sense_data.asc = ASC_MEDIUM_NOT_PRESENT;
 619+ cur_sense_data.ascq = 0;
 620+ }
 621+ break;
 622+ }
 623+
 624+ case SCSI_READ_10:
 625+ if (ejected)
 626+ {
 627+ send_command_failed_result();
 628+ cur_sense_data.sense_key = SENSE_NOT_READY;
 629+ cur_sense_data.asc = ASC_MEDIUM_NOT_PRESENT;
 630+ cur_sense_data.ascq = 0;
 631+ break;
 632+ }
 633+ cur_cmd.sector = (cbw->command_block[2] << 24 | cbw->command_block[3] << 16
 634+ | cbw->command_block[4] << 8 | cbw->command_block[5]);
 635+ cur_cmd.count = (cbw->command_block[7] << 8 | cbw->command_block[8]);
 636+ cur_cmd.orig_count = cur_cmd.count;
 637+
 638+ if ((cur_cmd.sector + cur_cmd.count) > storage_info.num_sectors)
 639+ {
 640+ send_csw(1);
 641+ cur_sense_data.sense_key = SENSE_ILLEGAL_REQUEST;
 642+ cur_sense_data.asc = ASC_LBA_OUT_OF_RANGE;
 643+ cur_sense_data.ascq = 0;
 644+ }
 645+ else send_and_read_next();
 646+ break;
 647+
 648+ case SCSI_WRITE_10:
 649+ if (ejected)
 650+ {
 651+ send_command_failed_result();
 652+ cur_sense_data.sense_key = SENSE_NOT_READY;
 653+ cur_sense_data.asc = ASC_MEDIUM_NOT_PRESENT;
 654+ cur_sense_data.ascq = 0;
 655+ break;
 656+ }
 657+ cur_cmd.sector = (cbw->command_block[2] << 24 | cbw->command_block[3] << 16
 658+ | cbw->command_block[4] << 8 | cbw->command_block[5]);
 659+ cur_cmd.count = (cbw->command_block[7] << 8 | cbw->command_block[8]);
 660+ cur_cmd.orig_count = cur_cmd.count;
 661+
 662+ if ((cur_cmd.sector + cur_cmd.count) > storage_info.num_sectors)
 663+ {
 664+ send_csw(1);
 665+ cur_sense_data.sense_key = SENSE_ILLEGAL_REQUEST;
 666+ cur_sense_data.asc = ASC_LBA_OUT_OF_RANGE;
 667+ cur_sense_data.ascq = 0;
 668+ }
 669+ else {
 670+ receive_block_data(storage_buffer, MIN(maxlen, cur_cmd.count * storage_info.sector_size));
 671+ }
 672+ break;
 673+
 674+ case SCSI_WRITE_BUFFER:
 675+ break;
 676+
 677+ default:
 678+ send_csw(1);
 679+ cur_sense_data.sense_key = SENSE_ILLEGAL_REQUEST;
 680+ cur_sense_data.asc = ASC_INVALID_COMMAND;
 681+ cur_sense_data.ascq = 0;
 682+ break;
 683+ }
 684+}
 685+
 686+int handle_ctrl_request(const struct usb_instance* data, int interface, union usb_ep0_buffer* request, const void** response)
 687+{
 688+ int size = -1;
 689+ switch (request->setup.bmRequestType.type)
 690+ {
 691+ case USB_SETUP_BMREQUESTTYPE_TYPE_CLASS:
 692+ switch (request->setup.bRequest.raw)
 693+ {
 694+ case 0xfe: // GET_MAX_LUN
 695+ data->buffer->raw[0] = 0;
 696+ size = 1;
 697+ break;
 698+ case 0xff: // STORAGE_RESET
 699+ size = 0;
 700+ break;
 701+ default: break;
 702+ }
 703+ break;
 704+ default: break;
 705+ }
 706+ return size;
 707+}
 708+
 709+void handle_set_altsetting(const struct usb_instance* data, int interface, int altsetting)
 710+{
 711+ usb = data;
 712+ state = WAITING_FOR_COMMAND;
 713+ maxlen = maxpacket * MIN(usb_get_max_transfer_size(usb, outep), usb_get_max_transfer_size(usb, inep));
 714+ usb_configure_ep(usb, outep, USB_ENDPOINT_TYPE_BULK, maxpacket);
 715+ usb_configure_ep(usb, inep, USB_ENDPOINT_TYPE_BULK, maxpacket);
 716+ listen();
 717+}
 718+
 719+void handle_unset_altsetting(const struct usb_instance* data, int interface, int altsetting)
 720+{
 721+ usb_unconfigure_ep(usb, outep);
 722+ usb_unconfigure_ep(usb, inep);
 723+}
 724+
 725+int handle_ep_ctrl_request(const struct usb_instance* data, int interface, int endpoint, union usb_ep0_buffer* request, const void** response)
 726+{
 727+ int size = -1;
 728+ switch (request->setup.bmRequestType.type)
 729+ {
 730+ case USB_SETUP_BMREQUESTTYPE_TYPE_STANDARD:
 731+ switch (request->setup.bRequest.req)
 732+ {
 733+ case USB_SETUP_BREQUEST_CLEAR_FEATURE:
 734+ if (request->setup.wLength || request->setup.wValue) break;
 735+ listen();
 736+ break;
 737+ default: break;
 738+ }
 739+ break;
 740+ default: break;
 741+ }
 742+ return size;
 743+}
 744+
 745+void handle_xfer_complete(const struct usb_instance* data, int ifnum, int epnum, int bytesleft)
 746+{
 747+ length -= bytesleft;
 748+ switch (state)
 749+ {
 750+ case RECEIVING_BLOCKS:
 751+ if (length != storage_info.sector_size * cur_cmd.count && length != maxlen) break;
 752+
 753+ pending_op_start = cur_cmd.sector;
 754+ pending_op_count = cur_cmd.count;
 755+ pending_op = OP_WRITE;
 756+ wakeup_signal(&pending_op_wakeup);
 757+ break;
 758+ case WAITING_FOR_CSW_COMPLETION:
 759+ state = WAITING_FOR_COMMAND;
 760+ listen();
 761+ break;
 762+ case WAITING_FOR_COMMAND:
 763+ handle_scsi(&cbw);
 764+ break;
 765+ case SENDING_RESULT:
 766+ send_csw(0);
 767+ break;
 768+ case SENDING_FAILED_RESULT:
 769+ send_csw(1);
 770+ break;
 771+ case SENDING_BLOCKS:
 772+ if (!cur_cmd.count) send_csw(0);
 773+ else send_and_read_next();
 774+ break;
 775+ }
 776+}
 777+
 778+void handle_timeout(const struct usb_instance* data, int interface, int endpoint, int bytesleft)
 779+{
 780+ usb_set_stall(usb, outep, true);
 781+ usb_set_stall(usb, inep, true);
 782+}
 783+
 784+static void handle_bus_reset(const struct usb_instance* data, int configuration, int interface, int highspeed)
 785+{
 786+ maxpacket = highspeed ? 512 : 64;
 787+ usb_config1_descriptors.c1_i0_a0_e1out.wMaxPacketSize = maxpacket;
 788+ usb_config1_descriptors.c1_i0_a0_e1in.wMaxPacketSize = maxpacket;
 789+}
 790+
 791+static struct usb_endpoint usb_c1_i0_a0_ep1out =
 792+{
 793+ .number = { .number = 0, .direction = USB_ENDPOINT_DIRECTION_OUT },
 794+ .ctrl_request = handle_ep_ctrl_request,
 795+ .xfer_complete = handle_xfer_complete,
 796+};
 797+
 798+static struct usb_endpoint usb_c1_i0_a0_ep1in =
 799+{
 800+ .number = { .number = 0, .direction = USB_ENDPOINT_DIRECTION_IN },
 801+ .ctrl_request = handle_ep_ctrl_request,
 802+ .xfer_complete = handle_xfer_complete,
 803+ .timeout = handle_timeout,
 804+};
 805+
 806+static const struct usb_altsetting usb_c1_i0_a0 =
 807+{
 808+ .set_altsetting = handle_set_altsetting,
 809+ .unset_altsetting = handle_unset_altsetting,
 810+ .endpoint_count = 2,
 811+ .endpoints =
 812+ {
 813+ &usb_c1_i0_a0_ep1out,
 814+ &usb_c1_i0_a0_ep1in,
 815+ },
 816+};
 817+
 818+static const struct usb_interface usb_c1_i0 =
 819+{
 820+ .bus_reset = handle_bus_reset,
 821+ .ctrl_request = handle_ctrl_request,
 822+ .altsetting_count = 1,
 823+ .altsettings =
 824+ {
 825+ &usb_c1_i0_a0,
 826+ },
 827+};
 828+
 829+static const struct usb_configuration usb_c1 =
 830+{
 831+ .descriptor = &usb_config1_descriptors.c1,
 832+ .set_configuration = NULL,
 833+ .unset_configuration = NULL,
 834+ .interface_count = 1,
 835+ .interfaces =
 836+ {
 837+ &usb_c1_i0,
 838+ },
 839+};
 840+
 841+static const struct usb_configuration* usb_configurations[] =
 842+{
 843+ &usb_c1,
 844+};
 845+
 846+static void main(int argc, const char** argv)
 847+{
 848+ storage_get_info(0, &storage_info);
 849+
 850+ if (!storage_info.sector_size) panicf(PANIC_KILLTHREAD, "Sector size is zero!\n");
 851+ if (!storage_info.num_sectors) panicf(PANIC_KILLTHREAD, "Number of sectors is zero!\n");
 852+
 853+ disk_unmount(0);
 854+
 855+ int i;
 856+ uint32_t eps = usbmanager_get_available_endpoints();
 857+ int ep_out = 0;
 858+ int ep_in = 0;
 859+ for (i = 1; i < 16; i++)
 860+ if (eps & (1 << i))
 861+ {
 862+ ep_out = i;
 863+ break;
 864+ }
 865+ for (i = 1; i < 16; i++)
 866+ if (eps & (1 << (16 + i)))
 867+ {
 868+ ep_in = i;
 869+ break;
 870+ }
 871+ if (!ep_out || !ep_in) panicf(PANIC_KILLTHREAD, "Not enough USB endpoints available!\n");
 872+ usb_config1_descriptors.c1_i0_a0_e1out.bEndpointAddress.number = ep_out;
 873+ usb_config1_descriptors.c1_i0_a0_e1in.bEndpointAddress.number = ep_in;
 874+ usb_c1_i0_a0_ep1out.number.number = ep_out;
 875+ usb_c1_i0_a0_ep1in.number.number = ep_in;
 876+ outep.number = ep_out;
 877+ inep.number = ep_in;
 878+ int rc = usbmanager_install_custom(&usb_devicedescriptor, ARRAYLEN(usb_configurations), usb_configurations,
 879+ ARRAYLEN(usb_stringdescriptors), usb_stringdescriptors, true);
 880+ if (IS_ERR(rc)) {
 881+ disk_mount(0);
 882+ panicf(PANIC_KILLTHREAD, "Failed to register USB handler: %08X\n", rc);
 883+ }
 884+
 885+ wakeup_init(&pending_op_wakeup);
 886+
 887+ while (!ejected && usbmanager_get_connected()) {
 888+ if (wakeup_wait(&pending_op_wakeup, 200000) == THREAD_OK) {
 889+ if (pending_op == OP_READ) {
 890+ //cprintf(3, "R(%u, %u)\n", pending_op_start, pending_op_count);
 891+ storage_read_sectors_md(0, pending_op_start, pending_op_count, storage_buffer);
 892+
 893+ send_block_data(storage_buffer, MIN(maxlen, cur_cmd.count * storage_info.sector_size));
 894+ }
 895+
 896+ if (pending_op == OP_WRITE) {
 897+ //cprintf(3, "W(%u, %u)\n", pending_op_start, pending_op_count);
 898+ storage_write_sectors_md(0, pending_op_start, pending_op_count, storage_buffer);
 899+ }
 900+
 901+ cur_cmd.sector += maxlen / storage_info.sector_size;
 902+ cur_cmd.count -= MIN(cur_cmd.count, maxlen / storage_info.sector_size);
 903+
 904+ if (pending_op == OP_WRITE) {
 905+ if (cur_cmd.count) {
 906+ receive_block_data(storage_buffer, MIN(maxlen, cur_cmd.count * storage_info.sector_size));
 907+ }
 908+ else send_csw(0);
 909+ }
 910+ }
 911+ }
 912+
 913+ usbmanager_uninstall_custom();
 914+
 915+ disk_mount(0);
 916+}
 917+
 918+
 919+EMCORE_APP_HEADER("Disk mode", main, 127)
Index: apps/diskmode/version.h
@@ -0,0 +1,36 @@
 2+//
 3+//
 4+// Copyright 2010 TheSeven
 5+//
 6+//
 7+// This file is part of emCORE.
 8+//
 9+// emCORE is free software: you can redistribute it and/or
 10+// modify it under the terms of the GNU General Public License as
 11+// published by the Free Software Foundation, either version 2 of the
 12+// License, or (at your option) any later version.
 13+//
 14+// emCORE is distributed in the hope that it will be useful,
 15+// but WITHOUT ANY WARRANTY; without even the implied warranty of
 16+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 17+// See the GNU General Public License for more details.
 18+//
 19+// You should have received a copy of the GNU General Public License along
 20+// with emCORE. If not, see <http://www.gnu.org/licenses/>.
 21+//
 22+//
 23+
 24+
 25+#ifndef __VERSION_H__
 26+#define __VERSION_H__
 27+
 28+
 29+#define VERSION "0.0.1pre"
 30+#define VERSION_MAJOR 0
 31+#define VERSION_MINOR 0
 32+#define VERSION_PATCH 1
 33+#define VERSION_SVN "$REVISION$"
 34+#define VERSION_SVN_INT $REVISIONINT$
 35+
 36+
 37+#endif
\ No newline at end of file
Index: apps/diskmode/SOURCES
@@ -0,0 +1 @@
 2+main.c
Index: apps/diskmode/ls.x
@@ -0,0 +1,42 @@
 2+ENTRY(__emcore_entrypoint)
 3+OUTPUT_FORMAT(elf32-littlearm)
 4+OUTPUT_ARCH(arm)
 5+
 6+MEMORY
 7+{
 8+ VIRTUAL : ORIGIN = 0x00000000, LENGTH = 0x10000000
 9+}
 10+
 11+SECTIONS
 12+{
 13+ .text :
 14+ {
 15+ __emcore_app_base = .;
 16+ KEEP(.emcoreentrypoint*)
 17+ *(.emcoreentrypoint*)
 18+ *(.text*)
 19+ *(.glue_7)
 20+ *(.glue_7t)
 21+ . = ALIGN(0x10);
 22+ } > VIRTUAL
 23+
 24+ .data :
 25+ {
 26+ *(.rodata*)
 27+ . = ALIGN(0x4);
 28+ *(.data*)
 29+ . = ALIGN(0x10);
 30+ } > VIRTUAL
 31+
 32+ .bss (NOLOAD) :
 33+ {
 34+ *(.bss*)
 35+ *(COMMON)
 36+ } > VIRTUAL
 37+
 38+ /DISCARD/ :
 39+ {
 40+ *(.eh_frame)
 41+ }
 42+
 43+}