ReactOS  0.4.13-dev-563-g0561610
id_badblock.cpp
Go to the documentation of this file.
1 /*++
2 
3 Copyright (C) 2006 VorontSOFT
4 
5 Module Name:
6  id_badblock.cpp
7 
8 Abstract:
9  This is the artificial badblock simulation part of the
10  miniport driver for ATA/ATAPI IDE controllers with Busmaster DMA support
11 
12 Author:
13  Nikolai Vorontsov (NickViz)
14 
15 Environment:
16  kernel mode only
17 
18 Notes:
19 
20  THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21  IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22  OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 
31 Revision History:
32  2006/08/03 Initial implementation.
33  2006/08/06 Added registry work.
34  2007/03/27 Added device serial to registry value name instead of LUN.
35 
36 --*/
37 
38 #include "stdafx.h"
39 
40 //#define MAX_BADBLOCKS_ITEMS 512
41 
42 
43 
44 //SBadBlockRange arrBadBlocks[MAX_BADBLOCKS_ITEMS];
45 //ULONG nBadBlocks = 0;
46 
49 
50 // RtlQueryRegistryValues callback function
51 static NTSTATUS __stdcall
59  )
60 {
63  ULONG i;
64  // The ValueType should be REG_SZ
65  // The ValueData is UNICODE string of the following format:
66  // "badblocks_start_from_lba badblocks_end_at_lba"
67 
68  KdPrint(( "BadBlockQueryRoutine: S/N:%S\n type %#x, len %#x\n", ValueName, ValueType, ValueLength));
69 
70  if(!BBListInited)
71  return STATUS_SUCCESS;
72 
73  if((ValueType == REG_BINARY) && // STRING
74  ValueLength && // At least "0 0 0"
75  !(ValueLength % sizeof(SBadBlockRange))) // There is free space for the record
76  {
77  cur = NULL;
78  link = BBList.Flink;
79  while(link != &BBList) {
81  link = link->Flink;
82  if(!wcscmp(cur->SerNumStr, ValueName)) {
83  KdPrint(( "already loaded\n"));
84  if(cur->LunExt) {
85  cur->LunExt->nBadBlocks = 0;
86  cur->LunExt->arrBadBlocks = NULL;
87  cur->LunExt->bbListDescr = NULL;
88  cur->LunExt = NULL;
89  }
90  break;
91  }
92  }
93 
94  if(!cur) {
96  if(!cur)
97  return STATUS_SUCCESS;
98  } else {
99  if(cur->arrBadBlocks) {
100  ExFreePool(cur->arrBadBlocks);
101  cur->arrBadBlocks = NULL;
102  }
103  }
105  if(!cur->arrBadBlocks) {
106  ExFreePool(cur);
107  return STATUS_SUCCESS;
108  }
110  wcsncpy(cur->SerNumStr, ValueName, 127);
111  cur->SerNumStr[127] = 0;
112  cur->nBadBlocks = ValueLength/sizeof(SBadBlockRange);
113  cur->LunExt = NULL;
114  InitializeListHead(&cur->List);
115  InsertTailList(&BBList, &(cur->List));
116  for(i=0; i<cur->nBadBlocks; i++) {
117  KdPrint(( "BB: %I64x - %I64x\n", cur->arrBadBlocks[i].m_lbaStart, cur->arrBadBlocks[i].m_lbaEnd-1));
118  }
119  }
120  return STATUS_SUCCESS;
121 } // end BadBlockQueryRoutine()
122 
123 
124 void
125 NTAPI
127  IN PHW_LU_EXTENSION LunExt
128  )
129 {
130  RTL_QUERY_REGISTRY_TABLE QueryTable[2]; // Main record and zero filled end of array marker
131  WCHAR DevSerial[128];
132 #ifdef _DEBUG
133  UCHAR cDevSerial[128];
134  ULONG i;
135 #endif
136  ULONG Length;
138  PSBadBlockListItem cur;
139  // Read from the registry necessary badblock pairs and fill in arrBadBlocks array
140  // HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\UniATA\Parameters\BadBlocks
141 
142  if(!LunExt) {
143  // init
144  KdPrint(( "InitBadBlocks general\n"));
145  if(!BBListInited) {
147  BBListInited = TRUE;
148  }
149 
152  QueryTable[0].Name = NULL; // If Name is NULL, the QueryRoutine function
153  // specified for this table entry is called
154  // for all values associated with the current
155  // registry key.
158  QueryTable[0].DefaultData = 0;
159  QueryTable[0].DefaultLength = 0;
160 
162 
164  L"UniATA\\Parameters\\BadBlocks",
165  QueryTable, 0, 0);
166 
167 #ifdef _DEBUG
168  KdPrint(( "InitBadBlocks returned: %#x\n", status));
169 #else
171 #endif
172  } else {
173 
174  KdPrint(( "InitBadBlocks local\n"));
175  Length = EncodeVendorStr(DevSerial, (PUCHAR)LunExt->IdentifyData.ModelNumber, sizeof(LunExt->IdentifyData.ModelNumber));
176  DevSerial[Length] = '-';
177  Length++;
178  Length += EncodeVendorStr(DevSerial+Length, LunExt->IdentifyData.SerialNumber, sizeof(LunExt->IdentifyData.SerialNumber));
179 
180 #ifdef _DEBUG
181  KdPrint(( "LunExt %#x\n", LunExt));
182  for(i=0; i<Length; i++) {
183  cDevSerial[i] = (UCHAR)(DevSerial[i]);
184  }
185  cDevSerial[i] = 0;
186  KdPrint(( "S/N:%s\n", cDevSerial));
187 #endif
188 
189  LunExt->nBadBlocks = 0;
190  LunExt->arrBadBlocks = NULL;
191 
192  link = BBList.Flink;
193  while(link != &BBList) {
195  link = link->Flink;
196  if(cur->LunExt == LunExt) {
197  KdPrint(( " deassociate BB list (by LunExt)\n"));
198  cur->LunExt->nBadBlocks = 0;
199  cur->LunExt->arrBadBlocks = NULL;
200  cur->LunExt->bbListDescr = NULL;
201  cur->LunExt = NULL;
202  } else
203  if(!wcscmp(cur->SerNumStr, DevSerial)) {
204  KdPrint(( " deassociate BB list (by Serial)\n"));
205  if(cur->LunExt) {
206  cur->LunExt->nBadBlocks = 0;
207  cur->LunExt->arrBadBlocks = NULL;
208  cur->LunExt->bbListDescr = NULL;
209  cur->LunExt = NULL;
210  }
211  }
212  }
213 
214  if(!(LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE)) {
215 
216  link = BBList.Flink;
217  while(link != &BBList) {
219  link = link->Flink;
220  if(!wcscmp(cur->SerNumStr, DevSerial)) {
221  KdPrint(( "found BB:List\n"));
222  cur->LunExt = LunExt;
223  LunExt->arrBadBlocks = cur->arrBadBlocks;
224  LunExt->nBadBlocks = cur->nBadBlocks;
225  LunExt->bbListDescr = cur;
226  return;
227  }
228  }
229  }
230  }
231  return;
232 } // end InitBadBlocks()
233 
234 
235 void
236 NTAPI
238  IN PHW_LU_EXTENSION LunExt
239  )
240 {
241  if(LunExt->bbListDescr) {
242  LunExt->bbListDescr->LunExt = NULL;
243  LunExt->nBadBlocks = 0;
244  LunExt->arrBadBlocks = NULL;
245  LunExt->bbListDescr = NULL;
246  }
247 } // end ForgetBadBlocks()
248 
249 bool
250 NTAPI
252  IN PHW_LU_EXTENSION LunExt,
253 // IN UCHAR command,
254  IN ULONGLONG lba,
255  IN ULONG count
256  )
257 {
258  if (LunExt->nBadBlocks == 0)
259  return false;
260 /*
261  // this is checked by caller
262  if(!(AtaCommandFlags[command] & ATA_CMD_FLAG_LBAsupp)) {
263  return false;
264 */
265  ULONG nBadBlocks = LunExt->nBadBlocks;
266  SBadBlockRange* arrBadBlocks = LunExt->arrBadBlocks;
267 
268  // back transform for possibly CHS'ed LBA
270 
271  for (ULONG i = 0; i < nBadBlocks; i++)
272  {
273  if (lba + count > arrBadBlocks->m_lbaStart &&
274  lba < arrBadBlocks->m_lbaEnd) {
275  KdPrint(( "listed BB @ %I64x\n", lba));
276  return true;
277  }
278  arrBadBlocks++;
279  }
280 
281  return false;
282 
283 } // end CheckIfBadBlock()
_In_ PCWSTR _Inout_ _At_ QueryTable _Pre_unknown_ PRTL_QUERY_REGISTRY_TABLE QueryTable
Definition: rtlfuncs.h:3988
#define IN
Definition: typedefs.h:38
#define TRUE
Definition: types.h:120
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
ULONG EncodeVendorStr(OUT char *Buffer, IN PUCHAR Str, IN ULONG Length, IN ULONG Xorer)
Definition: atactl.cpp:524
#define REG_BINARY
Definition: nt_native.h:1496
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:323
uint16_t * PWSTR
Definition: typedefs.h:54
GLuint GLuint GLsizei count
Definition: gl.h:1545
unsigned char * PUCHAR
Definition: retypes.h:3
_In_ PCWSTR _In_z_ PCWSTR _In_ ULONG ValueType
Definition: rtlfuncs.h:4000
LONG NTSTATUS
Definition: precomp.h:26
ULONGLONG NTAPI UniAtaCalculateLBARegsBack(struct _HW_LU_EXTENSION *LunExt, ULONGLONG lba)
#define DFLAGS_ATAPI_DEVICE
Definition: atapi.h:41
#define InsertTailList(ListHead, Entry)
#define RTL_REGISTRY_SERVICES
Definition: nt_native.h:162
#define lba
struct _SBadBlockListItem * bbListDescr
Definition: bsmaster.h:1201
_In_ PUNICODE_STRING ValueName
Definition: cmfuncs.h:264
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
PRTL_QUERY_REGISTRY_ROUTINE QueryRoutine
Definition: nt_native.h:109
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
void NTAPI ForgetBadBlocks(IN PHW_LU_EXTENSION LunExt)
unsigned char BOOLEAN
_In_ PCWSTR _Inout_ _At_ QueryTable EntryContext
Definition: rtlfuncs.h:3988
smooth NULL
Definition: ftsmooth.c:416
LIST_ENTRY BBList
Definition: id_badblock.cpp:47
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
WCHAR SerNumStr[128]
Definition: badblock.h:53
struct _SBadBlockRange SBadBlockRange
LIST_ENTRY List
Definition: psmgr.c:57
PHW_LU_EXTENSION LunExt
Definition: badblock.h:52
__wchar_t WCHAR
Definition: xmlstorage.h:180
uint64_t ULONGLONG
Definition: typedefs.h:65
BOOLEAN BBListInited
Definition: id_badblock.cpp:48
_In_ GUID _In_ PVOID ValueData
Definition: hubbusif.h:311
#define __stdcall
Definition: typedefs.h:25
NTSYSAPI NTSTATUS WINAPI RtlQueryRegistryValues(ULONG, PCWSTR, PRTL_QUERY_REGISTRY_TABLE, PVOID, PVOID)
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
ULONGLONG m_lbaStart
Definition: badblock.h:46
unsigned char UCHAR
Definition: xmlstorage.h:181
struct _SBadBlockListItem * PSBadBlockListItem
static const WCHAR L[]
Definition: oid.c:1250
_In_ GUID _In_ PVOID _In_ ULONG ValueLength
Definition: hubbusif.h:311
#define ExAllocatePool(type, size)
Definition: fbtusb.h:44
ULONGLONG m_lbaEnd
Definition: badblock.h:47
Definition: typedefs.h:117
struct _SBadBlockRange * arrBadBlocks
Definition: bsmaster.h:1202
_Check_return_ _CRTIMP int __cdecl wcscmp(_In_z_ const wchar_t *_Str1, _In_z_ const wchar_t *_Str2)
_CRTIMP wchar_t *__cdecl wcsncpy(wchar_t *_Dest, const wchar_t *_Source, size_t _Count)
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
void NTAPI InitBadBlocks(IN PHW_LU_EXTENSION LunExt)
static NTSTATUS __stdcall BadBlockQueryRoutine(IN PWSTR ValueName, IN ULONG ValueType, IN PVOID ValueData, IN ULONG ValueLength, IN PVOID Context, IN PVOID EntryContext)
Definition: id_badblock.cpp:52
unsigned int ULONG
Definition: retypes.h:1
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
const WCHAR * link
Definition: db.cpp:985
#define REG_NONE
Definition: nt_native.h:1492
return STATUS_SUCCESS
Definition: btrfs.c:2777
#define RTL_QUERY_REGISTRY_REQUIRED
Definition: nt_native.h:132
#define KdPrint(x)
Definition: env_spec_w32.h:288
LIST_ENTRY List
Definition: badblock.h:51
SBadBlockRange * arrBadBlocks
Definition: badblock.h:54
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
bool NTAPI CheckIfBadBlock(IN PHW_LU_EXTENSION LunExt, IN ULONGLONG lba, IN ULONG count)
Definition: ps.c:97