Partilhar via


Proteger solicitações digitais que usam E/S direta

O exemplo de código a seguir ilustra como um driver usa uma solicitação de comando para recuperar o conteúdo do FBR (registro básico de função) de um dispositivo. Como a quantidade de dados recuperados é pequena, o exemplo usa um comando de E/S direto (chamado CMD52 na especificação SD), que instrui o motorista do barramento a transmitir os dados pela linha CMD. Para ver um exemplo de código que ilustra como usar a E/S estendida (chamada CMD53 na especificação de SD), confira Solicitações Digitais Seguras que Usam E/S Estendida.

    const SDCMD_DESCRIPTOR ReadIoDirectDesc =
    {SDCMD_IO_RW_DIRECT, SDCC_STANDARD, SDTD_READ,
    SDTT_CMD_ONLY, SDRT_5};
    
    PSDBUS_REQUEST_PACKET sdrp = NULL;
    SD_RW_DIRECT_ARGUMENT sdIoArgument;
    
    sdrp = ExAllocatePool(NonPagedPool, 
        sizeof(SDBUS_REQUEST_PACKET));
    if (!sdrp) {
        return STATUS_INSUFFICIENT_RESOURCES;
    }
    RtlZeroMemory(sdrp, sizeof(SDBUS_REQUEST_PACKET));
    sdrp->RequestFunction = SDRF_DEVICE_COMMAND;
    sdrp->Parameters.DeviceCommand.CmdDesc = ReadIoDirectDesc;
    
    // Set up the argument and command descriptor
    
    sdIoArgument.u.AsULONG = 0;
    sdIoArgument.u.bits.Address = Offset;
    
    // Function # must be initialized by SdBus GetProperty call
    
    sdIoArgument.u.bits.Function = pDevExt->FunctionNumber;
    sdrp->Parameters.DeviceCommand.Argument = sdIoArgument.u.AsULONG;
    
    // Submit the request
    
    status = SdBusSubmitRequest(pDevExt->BusInterface.Context, sdrp);
    
    if (NT_SUCCESS(status)) {
        // for direct I/O, the data comes in the response
        *Data = sdrp->ResponseData.AsUCHAR[0];
    }
    ExFreePool(sdrp);

Para ler o FBR, o exemplo de código executa as seguintes etapas:

  1. Inicializar o descritor

    A primeira etapa no envio de uma solicitação device-command é definir um descritor de comando SD , SDCMD_DESCRIPTOR. Normalmente, um descritor é definido como uma estrutura de dados constante. O descritor no exemplo de código define uma operação de leitura com os seguintes elementos:

    Elemento Descrição

    SD_COMMAND_CODE

    A operação definida pelo descritor lê um único byte de dados do FBR, portanto, o exemplo de código usa um comando de E/S direto (CMD52), que instrui o cartão a relatar os dados solicitados na linha CMD e não nas linhas DAT. O exemplo de código indica um comando direto de E/S atribuindo um valor de SDCMD_IO_RW_DIRECT a esse membro.

    SD_COMMAND_CLASS

    As operações de leitura pertencem ao conjunto de comandos padrão (códigos de comando 0 a 63), portanto, o valor atribuído a esse membro do descritor é SDCC_STANDARD.

    SD_TRANSFER_DIRECTION

    As operações de leitura exigem uma transferência do dispositivo para o host, portanto, o valor atribuído a esse membro do descritor é SDTD_READ.

    SD_TRANSFER_TYPE

    Essa operação lê uma pequena quantidade de dados de um registro pela linha CMD. O cartão não precisa enviar dados pelas linhas da DAT, portanto, esse membro recebe um valor de SDTT_CMD_ONLY.

    SD_RESPONSE_TYPE

    O descritor especifica um tipo de resposta de SDRT_5, o que significa que o cartão deve notificar o host de que a operação foi concluída com uma solicitação de interrupção. Para obter uma explicação da resposta R5, consulte a especificação associação de cartão multimídia .

  2. Inicialize o Pacote de Solicitação concluindo as seguintes etapas:

    1. Defina a função Request:

      Depois de criar um descritor SD, o exemplo de código inicializa o pacote de solicitação SDBUS_REQUEST_PACKET. O membro RequestFunction do pacote de solicitação especifica se a solicitação contém um comando de dispositivo (valor de SDRF_DEVICE_COMMAND) ou uma operação de propriedade (valor de SDRF_GET_PROPERTY ou SDRF_SET_PROPERTY). O exemplo de código inicia um comando de dispositivo para que ele defina o membro RequestFunction como SDRF_DEVICE_COMMAND.

    2. Carregar o Descritor de Comando: em seguida, o exemplo de código armazena o descritor recém-inicializado no membro Parameters.DeviceCommand.CmdDesc do pacote de solicitação.

    3. Inicialize o argumento de leitura/gravação:

      O pacote de solicitação contém uma estrutura SD_RW_DIRECT_ARGUMENT que contém o local dos dados que o driver de barramento recupera. Essa estrutura também armazena o número da função cujo espaço de E/S do qual o motorista do barramento lê. O código de exemplo recupera o número da função da extensão do dispositivo, o que implica que o driver recuperou anteriormente as informações do cartão (provavelmente quando iniciou o dispositivo) com uma solicitação SDRF_GET_PROPERTY e as armazenou na extensão do dispositivo.

  3. Enviar a solicitação

    Depois de inicializar o descritor e o pacote de solicitação, o exemplo de código usa a rotina de solicitação síncrona, SdBusSubmitRequest, para enviar a solicitação. A rotina de solicitação passa o pacote de solicitação e as informações de contexto da interface que o sistema forneceu ao driver quando abriu a interface SD. Como essa é uma solicitação síncrona, o driver deve estar em execução no IRQL com menos de DISPATCH_LEVEL.

  4. Resultados do comando

    Como o exemplo de código usa E/S direta, nenhum buffer de dados é necessário além do campo ResponseData no pacote de solicitação SD.