18b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* 28b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Block driver for RAW files (win32) 38b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * 48b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Copyright (c) 2006 Fabrice Bellard 58b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * 68b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Permission is hereby granted, free of charge, to any person obtaining a copy 78b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * of this software and associated documentation files (the "Software"), to deal 88b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * in the Software without restriction, including without limitation the rights 98b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * copies of the Software, and to permit persons to whom the Software is 118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * furnished to do so, subject to the following conditions: 128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * 138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * The above copyright notice and this permission notice shall be included in 148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * all copies or substantial portions of the Software. 158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * 168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * THE SOFTWARE. 238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "qemu-common.h" 258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "qemu-timer.h" 268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "block_int.h" 275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "module.h" 285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <windows.h> 298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <winioctl.h> 308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define FTYPE_FILE 0 328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define FTYPE_CD 1 338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define FTYPE_HARDDISK 2 348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projecttypedef struct BDRVRawState { 368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project HANDLE hfile; 378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int type; 388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project char drive_path[16]; /* format: "d:\" */ 398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} BDRVRawState; 408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint qemu_ftruncate64(int fd, int64_t length) 428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project LARGE_INTEGER li; 448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project LONG high; 458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project HANDLE h; 468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project BOOL res; 478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((GetVersion() & 0x80000000UL) && (length >> 32) != 0) 498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return -1; 508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project h = (HANDLE)_get_osfhandle(fd); 528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* get current position, ftruncate do not change position */ 548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project li.HighPart = 0; 558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project li.LowPart = SetFilePointer (h, 0, &li.HighPart, FILE_CURRENT); 568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (li.LowPart == 0xffffffffUL && GetLastError() != NO_ERROR) 578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return -1; 588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project high = length >> 32; 608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!SetFilePointer(h, (DWORD) length, &high, FILE_BEGIN)) 618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return -1; 628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project res = SetEndOfFile(h); 638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* back to old position */ 658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project SetFilePointer(h, li.LowPart, &li.HighPart, FILE_BEGIN); 668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return res ? 0 : -1; 678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int set_sparse(int fd) 708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DWORD returned; 728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return (int) DeviceIoControl((HANDLE)_get_osfhandle(fd), FSCTL_SET_SPARSE, 738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project NULL, 0, NULL, 0, &returned, NULL); 748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int raw_open(BlockDriverState *bs, const char *filename, int flags) 778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project BDRVRawState *s = bs->opaque; 79cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner int access_flags; 808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DWORD overlapped; 818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project s->type = FTYPE_FILE; 838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 84cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner if (flags & BDRV_O_RDWR) { 858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project access_flags = GENERIC_READ | GENERIC_WRITE; 868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project access_flags = GENERIC_READ; 888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 89cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner 908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project overlapped = FILE_ATTRIBUTE_NORMAL; 915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if ((flags & BDRV_O_NOCACHE)) 928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project overlapped |= FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH; 935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner else if (!(flags & BDRV_O_CACHE_WB)) 945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner overlapped |= FILE_FLAG_WRITE_THROUGH; 958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project s->hfile = CreateFile(filename, access_flags, 968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project FILE_SHARE_READ, NULL, 97cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner OPEN_EXISTING, overlapped, NULL); 988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (s->hfile == INVALID_HANDLE_VALUE) { 998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int err = GetLastError(); 1008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (err == ERROR_ACCESS_DENIED) 1028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return -EACCES; 1038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return -1; 1048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 1058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 0; 1068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 1078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int raw_read(BlockDriverState *bs, int64_t sector_num, 1095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner uint8_t *buf, int nb_sectors) 1108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 1118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project BDRVRawState *s = bs->opaque; 1128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project OVERLAPPED ov; 1138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DWORD ret_count; 1148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int ret; 1155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int64_t offset = sector_num * 512; 1165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int count = nb_sectors * 512; 1178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project memset(&ov, 0, sizeof(ov)); 1198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ov.Offset = offset; 1208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ov.OffsetHigh = offset >> 32; 1218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ret = ReadFile(s->hfile, buf, count, &ret_count, &ov); 1225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!ret) 1235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return ret_count; 1245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (ret_count == count) 1255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ret_count = 0; 1268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return ret_count; 1278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 1288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int raw_write(BlockDriverState *bs, int64_t sector_num, 1305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner const uint8_t *buf, int nb_sectors) 1318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 1328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project BDRVRawState *s = bs->opaque; 1338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project OVERLAPPED ov; 1348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DWORD ret_count; 1358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int ret; 1365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int64_t offset = sector_num * 512; 1375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int count = nb_sectors * 512; 1388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project memset(&ov, 0, sizeof(ov)); 1408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ov.Offset = offset; 1418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ov.OffsetHigh = offset >> 32; 1428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ret = WriteFile(s->hfile, buf, count, &ret_count, &ov); 1435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!ret) 1445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return ret_count; 1455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (ret_count == count) 1465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ret_count = 0; 1478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return ret_count; 1488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 1498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void raw_flush(BlockDriverState *bs) 1518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 1528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project BDRVRawState *s = bs->opaque; 1538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project FlushFileBuffers(s->hfile); 1548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 1558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void raw_close(BlockDriverState *bs) 1578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 1588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project BDRVRawState *s = bs->opaque; 1598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project CloseHandle(s->hfile); 1608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 1618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int raw_truncate(BlockDriverState *bs, int64_t offset) 1638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 1648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project BDRVRawState *s = bs->opaque; 1655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner LONG low, high; 1668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project low = offset; 1688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project high = offset >> 32; 1698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!SetFilePointer(s->hfile, low, &high, FILE_BEGIN)) 1708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return -EIO; 1718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!SetEndOfFile(s->hfile)) 1728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return -EIO; 1738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 0; 1748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 1758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int64_t raw_getlength(BlockDriverState *bs) 1778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 1788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project BDRVRawState *s = bs->opaque; 1798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project LARGE_INTEGER l; 1808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ULARGE_INTEGER available, total, total_free; 1818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DISK_GEOMETRY_EX dg; 1828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DWORD count; 1838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project BOOL status; 1848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch(s->type) { 1868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case FTYPE_FILE: 1875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner l.LowPart = GetFileSize(s->hfile, (PDWORD)&l.HighPart); 1888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (l.LowPart == 0xffffffffUL && GetLastError() != NO_ERROR) 1898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return -EIO; 1908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 1918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case FTYPE_CD: 1928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!GetDiskFreeSpaceEx(s->drive_path, &available, &total, &total_free)) 1938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return -EIO; 1948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project l.QuadPart = total.QuadPart; 1958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 1968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case FTYPE_HARDDISK: 1978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project status = DeviceIoControl(s->hfile, IOCTL_DISK_GET_DRIVE_GEOMETRY_EX, 1988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project NULL, 0, &dg, sizeof(dg), &count, NULL); 1998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (status != 0) { 2008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project l = dg.DiskSize; 2018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 2028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 2038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: 2048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return -EIO; 2058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 2068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return l.QuadPart; 2078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 2088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 2095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int raw_create(const char *filename, QEMUOptionParameter *options) 2108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 2118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int fd; 2125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int64_t total_size = 0; 2138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 2145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* Read out options */ 2155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner while (options && options->name) { 2165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!strcmp(options->name, BLOCK_OPT_SIZE)) { 2175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner total_size = options->value.n / 512; 2185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 2195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner options++; 2205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 2218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 2228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 2238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 0644); 2248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (fd < 0) 2258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return -EIO; 2268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project set_sparse(fd); 2278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ftruncate(fd, total_size * 512); 2288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project close(fd); 2298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 0; 2308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 2318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 2325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic QEMUOptionParameter raw_create_options[] = { 2335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner { 2345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner .name = BLOCK_OPT_SIZE, 2355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner .type = OPT_SIZE, 2365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner .help = "Virtual disk size" 2375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner }, 2385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner { NULL } 2395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}; 2408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 241cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerstatic BlockDriver bdrv_file = { 242cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner .format_name = "file", 243cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner .protocol_name = "file", 2445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner .instance_size = sizeof(BDRVRawState), 245cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner .bdrv_file_open = raw_open, 2465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner .bdrv_close = raw_close, 2475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner .bdrv_create = raw_create, 2485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner .bdrv_flush = raw_flush, 2495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner .bdrv_read = raw_read, 2505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner .bdrv_write = raw_write, 2515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner .bdrv_truncate = raw_truncate, 2525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner .bdrv_getlength = raw_getlength, 2535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner .create_options = raw_create_options, 2558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}; 2568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 2578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/***********************************************/ 2588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* host device */ 2598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 2608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int find_cdrom(char *cdrom_name, int cdrom_name_size) 2618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 2628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project char drives[256], *pdrv = drives; 2638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project UINT type; 2648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 2658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project memset(drives, 0, sizeof(drives)); 2668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project GetLogicalDriveStrings(sizeof(drives), drives); 2678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project while(pdrv[0] != '\0') { 2688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project type = GetDriveType(pdrv); 2698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch(type) { 2708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case DRIVE_CDROM: 2718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project snprintf(cdrom_name, cdrom_name_size, "\\\\.\\%c:", pdrv[0]); 2728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 0; 2738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 2748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 2758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project pdrv += lstrlen(pdrv) + 1; 2768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 2778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return -1; 2788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 2798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 2808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int find_device_type(BlockDriverState *bs, const char *filename) 2818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 2828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project BDRVRawState *s = bs->opaque; 2838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project UINT type; 2848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project const char *p; 2858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 2868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (strstart(filename, "\\\\.\\", &p) || 2878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project strstart(filename, "//./", &p)) { 2888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (stristart(p, "PhysicalDrive", NULL)) 2898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return FTYPE_HARDDISK; 2908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project snprintf(s->drive_path, sizeof(s->drive_path), "%c:\\", p[0]); 2918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project type = GetDriveType(s->drive_path); 2925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner switch (type) { 2935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case DRIVE_REMOVABLE: 2945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case DRIVE_FIXED: 2955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return FTYPE_HARDDISK; 2965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case DRIVE_CDROM: 2978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return FTYPE_CD; 2985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner default: 2998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return FTYPE_FILE; 3005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 3018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 3028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return FTYPE_FILE; 3038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 3048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 3058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 3065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int hdev_probe_device(const char *filename) 3075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 3085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (strstart(filename, "/dev/cdrom", NULL)) 3095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return 100; 3105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (is_windows_drive(filename)) 3115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return 100; 3125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return 0; 3135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 3145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 3158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int hdev_open(BlockDriverState *bs, const char *filename, int flags) 3168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 3178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project BDRVRawState *s = bs->opaque; 3188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int access_flags, create_flags; 3198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DWORD overlapped; 3208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project char device_name[64]; 3218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 3228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (strstart(filename, "/dev/cdrom", NULL)) { 3238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (find_cdrom(device_name, sizeof(device_name)) < 0) 3248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return -ENOENT; 3258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project filename = device_name; 3268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 3278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* transform drive letters into device name */ 3288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (((filename[0] >= 'a' && filename[0] <= 'z') || 3298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project (filename[0] >= 'A' && filename[0] <= 'Z')) && 3308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project filename[1] == ':' && filename[2] == '\0') { 3318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project snprintf(device_name, sizeof(device_name), "\\\\.\\%c:", filename[0]); 3328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project filename = device_name; 3338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 3348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 3358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project s->type = find_device_type(bs, filename); 3368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 337cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner if (flags & BDRV_O_RDWR) { 3388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project access_flags = GENERIC_READ | GENERIC_WRITE; 3398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 3408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project access_flags = GENERIC_READ; 3418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 3428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project create_flags = OPEN_EXISTING; 3438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 3448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project overlapped = FILE_ATTRIBUTE_NORMAL; 3455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if ((flags & BDRV_O_NOCACHE)) 3468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project overlapped |= FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH; 3475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner else if (!(flags & BDRV_O_CACHE_WB)) 3485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner overlapped |= FILE_FLAG_WRITE_THROUGH; 3498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project s->hfile = CreateFile(filename, access_flags, 3508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project FILE_SHARE_READ, NULL, 3518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project create_flags, overlapped, NULL); 3528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (s->hfile == INVALID_HANDLE_VALUE) { 3538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int err = GetLastError(); 3548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 3558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (err == ERROR_ACCESS_DENIED) 3568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return -EACCES; 3578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return -1; 3588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 3598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 0; 3608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 3618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 3628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if 0 3638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/***********************************************/ 3648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* removable device additional commands */ 3658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 3668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int raw_is_inserted(BlockDriverState *bs) 3678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 3688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 3698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 3708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 3718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int raw_media_changed(BlockDriverState *bs) 3728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 3738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return -ENOTSUP; 3748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 3758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 3768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int raw_eject(BlockDriverState *bs, int eject_flag) 3778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 3788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DWORD ret_count; 3798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 3808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (s->type == FTYPE_FILE) 3818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return -ENOTSUP; 3828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (eject_flag) { 3838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DeviceIoControl(s->hfile, IOCTL_STORAGE_EJECT_MEDIA, 3848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project NULL, 0, NULL, 0, &lpBytesReturned, NULL); 3858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 3868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DeviceIoControl(s->hfile, IOCTL_STORAGE_LOAD_MEDIA, 3878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project NULL, 0, NULL, 0, &lpBytesReturned, NULL); 3888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 3898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 3908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 3918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int raw_set_locked(BlockDriverState *bs, int locked) 3928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 3938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return -ENOTSUP; 3948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 3958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif 3968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 397cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerstatic int hdev_has_zero_init(BlockDriverState *bs) 398cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{ 399cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner return 0; 400cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner} 401cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner 4025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic BlockDriver bdrv_host_device = { 4035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner .format_name = "host_device", 404cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner .protocol_name = "host_device", 4055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner .instance_size = sizeof(BDRVRawState), 4065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner .bdrv_probe_device = hdev_probe_device, 407cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner .bdrv_file_open = hdev_open, 4085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner .bdrv_close = raw_close, 4095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner .bdrv_flush = raw_flush, 410cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner .bdrv_has_zero_init = hdev_has_zero_init, 4115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 4125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner .bdrv_read = raw_read, 4135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner .bdrv_write = raw_write, 4145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner .bdrv_getlength = raw_getlength, 4158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}; 4165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 417cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerstatic void bdrv_file_init(void) 4185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 419cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner bdrv_register(&bdrv_file); 4205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner bdrv_register(&bdrv_host_device); 4215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 4225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 423cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerblock_init(bdrv_file_init); 424