Partager via


Sécuriser les demandes numériques qui utilisent des E/S directes

L’exemple de code suivant montre comment un pilote utilise une demande de commande pour récupérer le contenu du registre de base des fonctions (FBR) d’un appareil. Étant donné que la quantité de données récupérées est faible, l’exemple utilise une commande d’E/S directe (appelée CMD52 dans la spécification SD), qui indique au pilote de bus de transmettre les données sur la ligne CMD. Pour voir un exemple de code illustrant comment utiliser les E/S étendues (appelées CMD53 dans la spécification SD), consultez Demandes numériques sécurisées qui utilisent des E/S étendues.

    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);

Pour lire le fichier FBR, l’exemple de code effectue les étapes suivantes :

  1. Initialiser le descripteur

    La première étape de l’envoi d’une demande device-command consiste à définir un descripteur de commande SD, SDCMD_DESCRIPTOR. En règle générale, un descripteur est défini comme une structure de données constante. Le descripteur dans l’exemple de code définit une opération de lecture avec les éléments suivants :

    Élément Description

    SD_COMMAND_CODE

    L’opération définie par le descripteur lit un seul octet de données à partir du fichier FBR, de sorte que l’exemple de code utilise une commande d’E/S directe (CMD52), qui indique au carte de signaler les données demandées sur la ligne CMD et non sur les lignes DAT. L’exemple de code indique une commande d’E/S directe en affectant une valeur de SDCMD_IO_RW_DIRECT à ce membre.

    SD_COMMAND_CLASS

    Les opérations de lecture appartiennent au jeu de commandes standard (codes de commande 0 à 63), de sorte que la valeur affectée à ce membre du descripteur est SDCC_STANDARD.

    SD_TRANSFER_DIRECTION

    Les opérations de lecture nécessitent un transfert de l’appareil vers l’hôte, de sorte que la valeur affectée à ce membre du descripteur est SDTD_READ.

    SD_TRANSFER_TYPE

    Cette opération lit une petite quantité de données d’un registre sur la ligne CMD. Le carte n’a pas besoin d’envoyer des données sur les lignes DAT. Par conséquent, une valeur de SDTT_CMD_ONLY est attribuée à ce membre.

    SD_RESPONSE_TYPE

    Le descripteur spécifie un type de réponse de SDRT_5, ce qui signifie que le carte doit informer l’hôte que l’opération s’est terminée avec une demande d’interruption. Pour obtenir une explication de la réponse R5, consultez la spécification MultiMedia Card Association .

  2. Initialisez le paquet de requête en effectuant les étapes suivantes :

    1. Définissez la fonction de demande :

      Après avoir créé un descripteur SD, l’exemple de code initialise le paquet de requête , SDBUS_REQUEST_PACKET. Le membre RequestFunction du paquet de requête spécifie si la requête contient une commande d’appareil (valeur de SDRF_DEVICE_COMMAND) ou une opération de propriété (valeur de SDRF_GET_PROPERTY ou SDRF_SET_PROPERTY). L’exemple de code initie une commande d’appareil, de sorte qu’il définit le membre RequestFunction sur SDRF_DEVICE_COMMAND.

    2. Charger le descripteur de commande : ensuite, l’exemple de code stocke le descripteur nouvellement initialisé dans le membre Parameters.DeviceCommand.CmdDesc du paquet de requête.

    3. Initialisez l’argument en lecture-écriture :

      Le paquet de requête contient une structure SD_RW_DIRECT_ARGUMENT qui contient l’emplacement des données que le pilote de bus récupère. Cette structure stocke également le numéro de la fonction dont l’espace d’E/S est lu par le pilote de bus. L’exemple de code récupère le numéro de fonction de l’extension de l’appareil, ce qui implique que le pilote a précédemment récupéré les informations du carte (probablement lorsqu’il a démarré l’appareil) avec une demande de SDRF_GET_PROPERTY et les a stockées dans l’extension de l’appareil.

  3. Envoyer la demande

    Après avoir initialisé le descripteur et le paquet de requête, l’exemple de code utilise la routine de requête synchrone, SdBusSubmitRequest, pour envoyer la demande. La routine de requête transmet le paquet de requête et les informations de contexte d’interface que le système a fournies au pilote lors de l’ouverture de l’interface SD. Étant donné qu’il s’agit d’une requête synchrone, le pilote doit s’exécuter à IRQL inférieur à DISPATCH_LEVEL.

  4. Résultats de la commande

    Étant donné que l’exemple de code utilise des E/S directes, aucune mémoire tampon de données n’est requise autre que le champ ResponseData dans le paquet de requête SD.