1 /** @file 2 Fat File System driver routines that support EFI driver model. 3 4 Copyright (c) 2005 - 2014, Intel Corporation. All rights reserved.<BR> 5 This program and the accompanying materials are licensed and made available 6 under the terms and conditions of the BSD License which accompanies this 7 distribution. The full text of the license may be found at 8 http://opensource.org/licenses/bsd-license.php 9 10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 12 13 **/ 14 15 #include "Fat.h" 16 17 /** 18 19 Register Driver Binding protocol for this driver. 20 21 @param ImageHandle - Handle for the image of this driver. 22 @param SystemTable - Pointer to the EFI System Table. 23 24 @retval EFI_SUCCESS - Driver loaded. 25 @return other - Driver not loaded. 26 27 **/ 28 EFI_STATUS 29 EFIAPI 30 FatEntryPoint ( 31 IN EFI_HANDLE ImageHandle, 32 IN EFI_SYSTEM_TABLE *SystemTable 33 ); 34 35 /** 36 37 Unload function for this image. Uninstall DriverBinding protocol. 38 39 @param ImageHandle - Handle for the image of this driver. 40 41 @retval EFI_SUCCESS - Driver unloaded successfully. 42 @return other - Driver can not unloaded. 43 44 **/ 45 EFI_STATUS 46 EFIAPI 47 FatUnload ( 48 IN EFI_HANDLE ImageHandle 49 ); 50 51 /** 52 53 Test to see if this driver can add a file system to ControllerHandle. 54 ControllerHandle must support both Disk IO and Block IO protocols. 55 56 @param This - Protocol instance pointer. 57 @param ControllerHandle - Handle of device to test. 58 @param RemainingDevicePath - Not used. 59 60 @retval EFI_SUCCESS - This driver supports this device. 61 @retval EFI_ALREADY_STARTED - This driver is already running on this device. 62 @return other - This driver does not support this device. 63 64 **/ 65 EFI_STATUS 66 EFIAPI 67 FatDriverBindingSupported ( 68 IN EFI_DRIVER_BINDING_PROTOCOL *This, 69 IN EFI_HANDLE Controller, 70 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath 71 ); 72 73 /** 74 75 Start this driver on ControllerHandle by opening a Block IO and Disk IO 76 protocol, reading Device Path. Add a Simple File System protocol to 77 ControllerHandle if the media contains a valid file system. 78 79 @param This - Protocol instance pointer. 80 @param ControllerHandle - Handle of device to bind driver to. 81 @param RemainingDevicePath - Not used. 82 83 @retval EFI_SUCCESS - This driver is added to DeviceHandle. 84 @retval EFI_ALREADY_STARTED - This driver is already running on DeviceHandle. 85 @retval EFI_OUT_OF_RESOURCES - Can not allocate the memory. 86 @return other - This driver does not support this device. 87 88 **/ 89 EFI_STATUS 90 EFIAPI 91 FatDriverBindingStart ( 92 IN EFI_DRIVER_BINDING_PROTOCOL *This, 93 IN EFI_HANDLE Controller, 94 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath 95 ); 96 97 /** 98 99 Stop this driver on ControllerHandle. 100 101 @param This - Protocol instance pointer. 102 @param ControllerHandle - Handle of device to stop driver on. 103 @param NumberOfChildren - Not used. 104 @param ChildHandleBuffer - Not used. 105 106 @retval EFI_SUCCESS - This driver is removed DeviceHandle. 107 @return other - This driver was not removed from this device. 108 109 **/ 110 EFI_STATUS 111 EFIAPI 112 FatDriverBindingStop ( 113 IN EFI_DRIVER_BINDING_PROTOCOL *This, 114 IN EFI_HANDLE Controller, 115 IN UINTN NumberOfChildren, 116 IN EFI_HANDLE *ChildHandleBuffer 117 ); 118 119 // 120 // DriverBinding protocol instance 121 // 122 EFI_DRIVER_BINDING_PROTOCOL gFatDriverBinding = { 123 FatDriverBindingSupported, 124 FatDriverBindingStart, 125 FatDriverBindingStop, 126 0xa, 127 NULL, 128 NULL 129 }; 130 131 /** 132 133 Register Driver Binding protocol for this driver. 134 135 @param ImageHandle - Handle for the image of this driver. 136 @param SystemTable - Pointer to the EFI System Table. 137 138 @retval EFI_SUCCESS - Driver loaded. 139 @return other - Driver not loaded. 140 141 **/ 142 EFI_STATUS 143 EFIAPI 144 FatEntryPoint ( 145 IN EFI_HANDLE ImageHandle, 146 IN EFI_SYSTEM_TABLE *SystemTable 147 ) 148 { 149 EFI_STATUS Status; 150 151 // 152 // Initialize the EFI Driver Library 153 // 154 Status = EfiLibInstallDriverBindingComponentName2 ( 155 ImageHandle, 156 SystemTable, 157 &gFatDriverBinding, 158 ImageHandle, 159 &gFatComponentName, 160 &gFatComponentName2 161 ); 162 ASSERT_EFI_ERROR (Status); 163 164 return Status; 165 } 166 167 /** 168 169 Unload function for this image. Uninstall DriverBinding protocol. 170 171 @param ImageHandle - Handle for the image of this driver. 172 173 @retval EFI_SUCCESS - Driver unloaded successfully. 174 @return other - Driver can not unloaded. 175 176 **/ 177 EFI_STATUS 178 EFIAPI 179 FatUnload ( 180 IN EFI_HANDLE ImageHandle 181 ) 182 { 183 EFI_STATUS Status; 184 EFI_HANDLE *DeviceHandleBuffer; 185 UINTN DeviceHandleCount; 186 UINTN Index; 187 VOID *ComponentName; 188 VOID *ComponentName2; 189 190 Status = gBS->LocateHandleBuffer ( 191 AllHandles, 192 NULL, 193 NULL, 194 &DeviceHandleCount, 195 &DeviceHandleBuffer 196 ); 197 if (EFI_ERROR (Status)) { 198 return Status; 199 } 200 201 for (Index = 0; Index < DeviceHandleCount; Index++) { 202 Status = EfiTestManagedDevice (DeviceHandleBuffer[Index], ImageHandle, &gEfiDiskIoProtocolGuid); 203 if (!EFI_ERROR (Status)) { 204 Status = gBS->DisconnectController ( 205 DeviceHandleBuffer[Index], 206 ImageHandle, 207 NULL 208 ); 209 if (EFI_ERROR (Status)) { 210 break; 211 } 212 } 213 } 214 215 if (Index == DeviceHandleCount) { 216 // 217 // Driver is stopped successfully. 218 // 219 Status = gBS->HandleProtocol (ImageHandle, &gEfiComponentNameProtocolGuid, &ComponentName); 220 if (EFI_ERROR (Status)) { 221 ComponentName = NULL; 222 } 223 224 Status = gBS->HandleProtocol (ImageHandle, &gEfiComponentName2ProtocolGuid, &ComponentName2); 225 if (EFI_ERROR (Status)) { 226 ComponentName2 = NULL; 227 } 228 229 if (ComponentName == NULL) { 230 if (ComponentName2 == NULL) { 231 Status = gBS->UninstallMultipleProtocolInterfaces ( 232 ImageHandle, 233 &gEfiDriverBindingProtocolGuid, &gFatDriverBinding, 234 NULL 235 ); 236 } else { 237 Status = gBS->UninstallMultipleProtocolInterfaces ( 238 ImageHandle, 239 &gEfiDriverBindingProtocolGuid, &gFatDriverBinding, 240 &gEfiComponentName2ProtocolGuid, ComponentName2, 241 NULL 242 ); 243 } 244 } else { 245 if (ComponentName2 == NULL) { 246 Status = gBS->UninstallMultipleProtocolInterfaces ( 247 ImageHandle, 248 &gEfiDriverBindingProtocolGuid, &gFatDriverBinding, 249 &gEfiComponentNameProtocolGuid, ComponentName, 250 NULL 251 ); 252 } else { 253 Status = gBS->UninstallMultipleProtocolInterfaces ( 254 ImageHandle, 255 &gEfiDriverBindingProtocolGuid, &gFatDriverBinding, 256 &gEfiComponentNameProtocolGuid, ComponentName, 257 &gEfiComponentName2ProtocolGuid, ComponentName2, 258 NULL 259 ); 260 } 261 } 262 } 263 264 if (DeviceHandleBuffer != NULL) { 265 FreePool (DeviceHandleBuffer); 266 } 267 268 return Status; 269 } 270 271 /** 272 273 Test to see if this driver can add a file system to ControllerHandle. 274 ControllerHandle must support both Disk IO and Block IO protocols. 275 276 @param This - Protocol instance pointer. 277 @param ControllerHandle - Handle of device to test. 278 @param RemainingDevicePath - Not used. 279 280 @retval EFI_SUCCESS - This driver supports this device. 281 @retval EFI_ALREADY_STARTED - This driver is already running on this device. 282 @return other - This driver does not support this device. 283 284 **/ 285 EFI_STATUS 286 EFIAPI 287 FatDriverBindingSupported ( 288 IN EFI_DRIVER_BINDING_PROTOCOL *This, 289 IN EFI_HANDLE ControllerHandle, 290 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath 291 ) 292 { 293 EFI_STATUS Status; 294 EFI_DISK_IO_PROTOCOL *DiskIo; 295 296 // 297 // Open the IO Abstraction(s) needed to perform the supported test 298 // 299 Status = gBS->OpenProtocol ( 300 ControllerHandle, 301 &gEfiDiskIoProtocolGuid, 302 (VOID **) &DiskIo, 303 This->DriverBindingHandle, 304 ControllerHandle, 305 EFI_OPEN_PROTOCOL_BY_DRIVER 306 ); 307 308 if (EFI_ERROR (Status)) { 309 return Status; 310 } 311 // 312 // Close the I/O Abstraction(s) used to perform the supported test 313 // 314 gBS->CloseProtocol ( 315 ControllerHandle, 316 &gEfiDiskIoProtocolGuid, 317 This->DriverBindingHandle, 318 ControllerHandle 319 ); 320 321 // 322 // Open the IO Abstraction(s) needed to perform the supported test 323 // 324 Status = gBS->OpenProtocol ( 325 ControllerHandle, 326 &gEfiBlockIoProtocolGuid, 327 NULL, 328 This->DriverBindingHandle, 329 ControllerHandle, 330 EFI_OPEN_PROTOCOL_TEST_PROTOCOL 331 ); 332 333 return Status; 334 } 335 336 /** 337 338 Start this driver on ControllerHandle by opening a Block IO and Disk IO 339 protocol, reading Device Path. Add a Simple File System protocol to 340 ControllerHandle if the media contains a valid file system. 341 342 @param This - Protocol instance pointer. 343 @param ControllerHandle - Handle of device to bind driver to. 344 @param RemainingDevicePath - Not used. 345 346 @retval EFI_SUCCESS - This driver is added to DeviceHandle. 347 @retval EFI_ALREADY_STARTED - This driver is already running on DeviceHandle. 348 @retval EFI_OUT_OF_RESOURCES - Can not allocate the memory. 349 @return other - This driver does not support this device. 350 351 **/ 352 EFI_STATUS 353 EFIAPI 354 FatDriverBindingStart ( 355 IN EFI_DRIVER_BINDING_PROTOCOL *This, 356 IN EFI_HANDLE ControllerHandle, 357 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath 358 ) 359 { 360 EFI_STATUS Status; 361 EFI_BLOCK_IO_PROTOCOL *BlockIo; 362 EFI_DISK_IO_PROTOCOL *DiskIo; 363 EFI_DISK_IO2_PROTOCOL *DiskIo2; 364 BOOLEAN LockedByMe; 365 366 LockedByMe = FALSE; 367 // 368 // Acquire the lock. 369 // If caller has already acquired the lock, cannot lock it again. 370 // 371 Status = FatAcquireLockOrFail (); 372 if (!EFI_ERROR (Status)) { 373 LockedByMe = TRUE; 374 } 375 376 Status = InitializeUnicodeCollationSupport (This->DriverBindingHandle); 377 if (EFI_ERROR (Status)) { 378 goto Exit; 379 } 380 // 381 // Open our required BlockIo and DiskIo 382 // 383 Status = gBS->OpenProtocol ( 384 ControllerHandle, 385 &gEfiBlockIoProtocolGuid, 386 (VOID **) &BlockIo, 387 This->DriverBindingHandle, 388 ControllerHandle, 389 EFI_OPEN_PROTOCOL_GET_PROTOCOL 390 ); 391 if (EFI_ERROR (Status)) { 392 goto Exit; 393 } 394 395 Status = gBS->OpenProtocol ( 396 ControllerHandle, 397 &gEfiDiskIoProtocolGuid, 398 (VOID **) &DiskIo, 399 This->DriverBindingHandle, 400 ControllerHandle, 401 EFI_OPEN_PROTOCOL_BY_DRIVER 402 ); 403 if (EFI_ERROR (Status)) { 404 goto Exit; 405 } 406 407 Status = gBS->OpenProtocol ( 408 ControllerHandle, 409 &gEfiDiskIo2ProtocolGuid, 410 (VOID **) &DiskIo2, 411 This->DriverBindingHandle, 412 ControllerHandle, 413 EFI_OPEN_PROTOCOL_BY_DRIVER 414 ); 415 if (EFI_ERROR (Status)) { 416 DiskIo2 = NULL; 417 } 418 419 // 420 // Allocate Volume structure. In FatAllocateVolume(), Resources 421 // are allocated with protocol installed and cached initialized 422 // 423 Status = FatAllocateVolume (ControllerHandle, DiskIo, DiskIo2, BlockIo); 424 425 // 426 // When the media changes on a device it will Reinstall the BlockIo interaface. 427 // This will cause a call to our Stop(), and a subsequent reentrant call to our 428 // Start() successfully. We should leave the device open when this happen. 429 // 430 if (EFI_ERROR (Status)) { 431 Status = gBS->OpenProtocol ( 432 ControllerHandle, 433 &gEfiSimpleFileSystemProtocolGuid, 434 NULL, 435 This->DriverBindingHandle, 436 ControllerHandle, 437 EFI_OPEN_PROTOCOL_TEST_PROTOCOL 438 ); 439 if (EFI_ERROR (Status)) { 440 gBS->CloseProtocol ( 441 ControllerHandle, 442 &gEfiDiskIoProtocolGuid, 443 This->DriverBindingHandle, 444 ControllerHandle 445 ); 446 gBS->CloseProtocol ( 447 ControllerHandle, 448 &gEfiDiskIo2ProtocolGuid, 449 This->DriverBindingHandle, 450 ControllerHandle 451 ); 452 } 453 } 454 455 Exit: 456 // 457 // Unlock if locked by myself. 458 // 459 if (LockedByMe) { 460 FatReleaseLock (); 461 } 462 return Status; 463 } 464 465 /** 466 467 Stop this driver on ControllerHandle. 468 469 @param This - Protocol instance pointer. 470 @param ControllerHandle - Handle of device to stop driver on. 471 @param NumberOfChildren - Not used. 472 @param ChildHandleBuffer - Not used. 473 474 @retval EFI_SUCCESS - This driver is removed DeviceHandle. 475 @return other - This driver was not removed from this device. 476 477 **/ 478 EFI_STATUS 479 EFIAPI 480 FatDriverBindingStop ( 481 IN EFI_DRIVER_BINDING_PROTOCOL *This, 482 IN EFI_HANDLE ControllerHandle, 483 IN UINTN NumberOfChildren, 484 IN EFI_HANDLE *ChildHandleBuffer 485 ) 486 { 487 EFI_STATUS Status; 488 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *FileSystem; 489 FAT_VOLUME *Volume; 490 EFI_DISK_IO2_PROTOCOL *DiskIo2; 491 492 DiskIo2 = NULL; 493 // 494 // Get our context back 495 // 496 Status = gBS->OpenProtocol ( 497 ControllerHandle, 498 &gEfiSimpleFileSystemProtocolGuid, 499 (VOID **) &FileSystem, 500 This->DriverBindingHandle, 501 ControllerHandle, 502 EFI_OPEN_PROTOCOL_GET_PROTOCOL 503 ); 504 505 if (!EFI_ERROR (Status)) { 506 Volume = VOLUME_FROM_VOL_INTERFACE (FileSystem); 507 DiskIo2 = Volume->DiskIo2; 508 Status = FatAbandonVolume (Volume); 509 } 510 511 if (!EFI_ERROR (Status)) { 512 if (DiskIo2 != NULL) { 513 Status = gBS->CloseProtocol ( 514 ControllerHandle, 515 &gEfiDiskIo2ProtocolGuid, 516 This->DriverBindingHandle, 517 ControllerHandle 518 ); 519 ASSERT_EFI_ERROR (Status); 520 } 521 Status = gBS->CloseProtocol ( 522 ControllerHandle, 523 &gEfiDiskIoProtocolGuid, 524 This->DriverBindingHandle, 525 ControllerHandle 526 ); 527 ASSERT_EFI_ERROR (Status); 528 } 529 530 return Status; 531 } 532