/*****************************************************************************
* diskwritter.cpp
*
* This file implements disk information and dumping files to disk
*
* Copyright (c) 2007-2011
* Qualcomm Technologies Incorporated.
* All Rights Reserved.
* Qualcomm Confidential and Proprietary
*
*****************************************************************************/
/*=============================================================================
Edit History
$Header: //source/qcom/qct/platform/uefi/workspaces/pweber/apps/8x26_emmcdl/emmcdl/main/latest/src/diskwriter.cpp#13 $
$DateTime: 2015/06/10 19:43:31 $ $Author: pweber $
when who what, where, why
-------------------------------------------------------------------------------
10/10/11 pgw Keep volume open otherwise windows will remount it on us
06/28/11 pgw Aligned all buffers to 128 bytes for ARM SDCC suport
05/18/11 pgw Changed to uint64 use local handle rather than passing it in
updated performance tests and API's.
04/13/11 pgw Fixed bug for empty card readers.
03/21/11 pgw Initial version.
=============================================================================*/
#include "diskwriter.h"
#include "winerror.h"
#include <winioctl.h>
#include <string.h>
#include <stdio.h>
#include "tchar.h"
#include "windows.h"
#include "sahara.h"
// Only List COM port information for desktop version
#ifndef ARM
#include "setupapi.h"
#define INITGUID 1 // This is needed to properly define the GUID's in devpkey.h
#include "devpkey.h"
#endif //ARM
DiskWriter::DiskWriter()
{
ovl.hEvent = CreateEvent(NULL, FALSE, FALSE,NULL);
hVolume = INVALID_HANDLE_VALUE;
bPatchDisk = false;
// Create some nice 128 byte aligned buffers required by ARM
disks = NULL;
volumes = NULL;
gpt_entries = (gpt_entry_t*)malloc(sizeof(gpt_entry_t)*256);
disks = (disk_entry_t*)malloc(sizeof(disk_entry_t)*MAX_DISKS);
volumes = (vol_entry_t*)malloc(sizeof(vol_entry_t)*MAX_VOLUMES);
}
DiskWriter::~DiskWriter()
{
if(disks) free(disks);
if(volumes) free(volumes);
CloseHandle(ovl.hEvent);
}
int DiskWriter::ProgramRawCommand(TCHAR *key)
{
UNREFERENCED_PARAMETER(key);
return ERROR_INVALID_FUNCTION;
}
int DiskWriter::DeviceReset(void)
{
return ERROR_INVALID_FUNCTION;
}
int DiskWriter::GetVolumeInfo(vol_entry_t *vol)
{
TCHAR mount[MAX_PATH+1];
DWORD mountsize;
//try {
// Clear out our mount path
memset(mount,0,sizeof(mount));
if( GetVolumePathNamesForVolumeName(vol->rootpath,mount,MAX_PATH,&mountsize) ) {
DWORD maxcomplen;
DWORD fsflags;
wcscpy_s(vol->mount, mount);
// Chop of the last trailing char
vol->mount[wcslen(vol->mount)-1] = 0;
vol->drivetype = GetDriveType(vol->mount);
// We only fill out information for DRIVE_FIXED and DRIVE_REMOVABLE
if( vol->drivetype == DRIVE_REMOVABLE || vol->drivetype == DRIVE_FIXED ) {
GetVolumeInformation(vol->mount,vol->volume,MAX_PATH+1,(LPDWORD)&vol->serialnum,&maxcomplen,&fsflags,vol->fstype,MAX_PATH);
// Create handle to volume and get disk number
TCHAR volPath[MAX_PATH+1] = _T("\\\\.\\");
wcscat_s(volPath,vol->mount);
// Create the file using the volume name
hDisk = CreateFile( volPath,
GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if( hDisk != INVALID_HANDLE_VALUE ) {
// Now get physical disk number
_STORAGE_DEVICE_NUMBER devInfo;
DWORD bytesRead;
DeviceIoControl( hDisk,IOCTL_STORAGE_GET_DEVICE_NUMBER,NULL,0,&devInfo,sizeof(devInfo),&bytesRead,NULL);
vol->disknum = devInfo.DeviceNumber;
CloseHandle(hDisk);
}
}
}
//} catch(exception &e) {
// wprintf(L"Exception in GetVolumeInfo: %s\n", e.what());
//}
return ERROR_SUCCESS;
}
int DiskWriter::GetDiskInfo(disk_entry_t *de)
{
TCHAR tPath[MAX_PATH+1];
int status = ERROR_SUCCESS;
// Create path to physical drive
swprintf_s(tPath, _T("\\\\.\\PhysicalDrive%i"), de->disknum);
// Create the file using the physical drive
hDisk = CreateFile(tPath,
GENERIC_READ,
(FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE),
NULL,
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,
NULL);
if (hDisk != INVALID_HANDLE_VALUE) {
DISK_GEOMETRY_EX info;
DWORD bytesRead;
if (DeviceIoControl(hDisk,
IOCTL_DISK_GET_DRIVE_GEOMETRY_EX, // dwIoControlCode
NULL, // lpInBuffer
0, // nInBufferSize
&info, // output buffer
sizeof(info), // size of output buffer
&bytesRead, // number of bytes returned
&ovl // OVERLAPPED structure
))
{
wcscpy_s(de->diskname, MAX_PATH, tPath);
de->disksize = *(uint64*)(&info.DiskSize);
de->blocksize = info.Geometry.BytesPerSector;
}
else {
status = ERROR_NO_VOLUME_LABEL;
}
CloseHandle(hDisk);
}
else {
status = GetLastError();
}
if (status != ERROR_SUCCESS) {
de->disknum = -1;
de->disksize = (uint64)-1;
de->diskname[0] = 0;
de->volnum[0] = -1;
}
return ERROR_SUCCESS;
}
int DiskWriter::InitDiskList(bool verbose)
{
HANDLE vHandle;
TCHAR VolumeName[MAX_PATH+1];
BOOL bValid = true;
int i=0;
#ifndef ARM
HDEVINFO hDevInfo = SetupDiGetClassDevs(&GUID_DEVINTERFACE_COMPORT,NULL,NULL,DIGCF_DEVICEINTERFACE|DIGCF_PRESENT);
DEVPROPTYPE ulPropertyType = DEVPROP_TYPE_STRING;
DWORD dwSize;
#endif //ARM
if( disks == NULL || volumes == NULL ) {
return ERROR_INVALID_PARAMETER;
}
wprintf(L"Finding all devices in emergency download mode...\n");
#ifndef ARM
if( hDevInfo != INVALID_HANDLE_VALUE ) {
// Successfully got a list of ports
for(int i=0; ;i++) {
WCHAR szBuffer[512];
SP_DEVINFO_DATA DeviceInfoData;
DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
if( !SetupDiEnumDeviceInfo(hDevInfo,i,&DeviceInfoData) && (GetLastError() == ERROR_NO_MORE_ITEMS) ) {
// No more ports
break;
}
// successfully found entry print out the info
if( SetupDiGetDeviceProperty(hDevInfo,&DeviceInfoData,&DEVPKEY_Device_FriendlyName,&ulPropertyType,(BYTE*)szBuffer, sizeof(szBuffer), &dwSize, 0)) {
if( (GetLastError() == ERROR_SUCCESS) && wcsstr(szBuffer,L"QDLoader 9008") != NULL ) {
wprintf(szBuffer);
// Get the serial number and display it if verbose is enabled
if (verbose)
{
WCHAR *port = wcsstr(szBuffer, L"COM");
if (port != NULL) {
SerialPort spTemp;
pbl_info_t pbl_info;
spTemp.Open(_wtoi((port + 3)));
Sahara sh(&spTemp);
int status = sh.DumpDeviceInfo(&pbl_info);
if (status == ERROR_SUCCESS) {
wprintf(L": SERIAL=0x%x : HW_ID=0x%x", pbl_info.serial, pbl_info.msm_id);
}
}
}
wprintf(_T("\n"));
}
}
}
SetupDiDestroyDeviceInfoList(hDevInfo);
}
#endif //ARM
memset(volumes,0,sizeof(vol_entry_t)*MAX_VOLUMES);
// Set all disks to invalid
for(i=0; i < MAX_VOLUMES; i++) {
volumes[i].disknum = -1;
}
wprintf(L"\nFinding all disks on computer ...\n");
// First loop through all the volumes
vHandle = FindFirstVolume(VolumeName,MAX_PATH);
for(i=