diff options
Diffstat (limited to 'firmware/target/arm/imx31/gigabeat-s/usb-gigabeat-s.c')
-rw-r--r-- | firmware/target/arm/imx31/gigabeat-s/usb-gigabeat-s.c | 44 |
1 files changed, 43 insertions, 1 deletions
diff --git a/firmware/target/arm/imx31/gigabeat-s/usb-gigabeat-s.c b/firmware/target/arm/imx31/gigabeat-s/usb-gigabeat-s.c index 016f24fc48..c52a9a6dec 100644 --- a/firmware/target/arm/imx31/gigabeat-s/usb-gigabeat-s.c +++ b/firmware/target/arm/imx31/gigabeat-s/usb-gigabeat-s.c | |||
@@ -19,7 +19,6 @@ | |||
19 | * | 19 | * |
20 | ****************************************************************************/ | 20 | ****************************************************************************/ |
21 | #include "config.h" | 21 | #include "config.h" |
22 | #include "cpu.h" | ||
23 | #include "system.h" | 22 | #include "system.h" |
24 | #include "kernel.h" | 23 | #include "kernel.h" |
25 | #include "ata.h" | 24 | #include "ata.h" |
@@ -31,8 +30,10 @@ | |||
31 | #include "ccm-imx31.h" | 30 | #include "ccm-imx31.h" |
32 | #include "avic-imx31.h" | 31 | #include "avic-imx31.h" |
33 | #include "power-gigabeat-s.h" | 32 | #include "power-gigabeat-s.h" |
33 | #include <string.h> | ||
34 | 34 | ||
35 | static int usb_status = USB_EXTRACTED; | 35 | static int usb_status = USB_EXTRACTED; |
36 | static bool bootloader_install_mode = false; | ||
36 | 37 | ||
37 | static void enable_transceiver(bool enable) | 38 | static void enable_transceiver(bool enable) |
38 | { | 39 | { |
@@ -106,6 +107,16 @@ void usb_enable(bool on) | |||
106 | 107 | ||
107 | void usb_attach(void) | 108 | void usb_attach(void) |
108 | { | 109 | { |
110 | bootloader_install_mode = false; | ||
111 | |||
112 | if (usb_core_driver_enabled(USB_DRIVER_MASS_STORAGE)) | ||
113 | { | ||
114 | /* Check if this will be bootloader install mode, exposing the | ||
115 | * boot partition instead of the data partition */ | ||
116 | bootloader_install_mode = | ||
117 | (button_status() & USB_BL_INSTALL_MODE_BTN) != 0; | ||
118 | } | ||
119 | |||
109 | usb_drv_attach(); | 120 | usb_drv_attach(); |
110 | } | 121 | } |
111 | 122 | ||
@@ -133,3 +144,34 @@ void usb_drv_usb_detect_event(void) | |||
133 | if (usb_drv_powered()) | 144 | if (usb_drv_powered()) |
134 | usb_status_event(USB_INSERTED); | 145 | usb_status_event(USB_INSERTED); |
135 | } | 146 | } |
147 | |||
148 | /* Called when reading the MBR */ | ||
149 | void usb_fix_mbr(unsigned char *mbr) | ||
150 | { | ||
151 | unsigned char* p = mbr + 0x1be; | ||
152 | char tmp[16]; | ||
153 | |||
154 | /* The Gigabeat S factory partition table contains invalid values for the | ||
155 | "active" flag in the MBR. This prevents at least the Linux kernel | ||
156 | from accepting the partition table, so we fix it on-the-fly. */ | ||
157 | p[0x00] &= 0x80; | ||
158 | p[0x10] &= 0x80; | ||
159 | p[0x20] &= 0x80; | ||
160 | p[0x30] &= 0x80; | ||
161 | |||
162 | if (bootloader_install_mode) | ||
163 | return; | ||
164 | |||
165 | /* Windows ignores the partition flags and mounts the first partition it | ||
166 | sees when the device reports itself as removable. Swap the partitions | ||
167 | so the data partition appears to be partition 0. Mark the boot | ||
168 | partition 0 as hidden and make it partition 1. */ | ||
169 | |||
170 | /* Mark the first partition as hidden */ | ||
171 | p[0x04] |= 0x10; | ||
172 | |||
173 | /* Swap first and second partitions */ | ||
174 | memcpy(tmp, &p[0x00], 16); | ||
175 | memcpy(&p[0x00], &p[0x10], 16); | ||
176 | memcpy(&p[0x10], tmp, 16); | ||
177 | } | ||