Поделиться через


Защита цифровых запросов, использующих прямой ввод-вывод

В следующем примере кода показано, как драйвер использует командный запрос для получения содержимого базового регистра функции устройства (FBR). Так как объем полученных данных невелик, в примере используется команда прямого ввода-вывода (которая называется CMD52 в спецификации SD), которая предписывает водителю шины передавать данные через линию CMD. Пример кода, демонстрирующий использование расширенных операций ввода-вывода (cmd53 в спецификации SD), см. в статье Защита цифровых запросов, использующих расширенный ввод-вывод.

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

Чтобы прочитать FBR, в примере кода выполняются следующие действия:

  1. Инициализация дескриптора

    Первым шагом при отправке запроса device-command является определение дескриптора команды SD , SDCMD_DESCRIPTOR. Как правило, дескриптор определяется как константная структура данных. Дескриптор в примере кода определяет операцию чтения со следующими элементами:

    Элемент Описание

    SD_COMMAND_CODE

    Операция, определяемая дескриптором, считывает один байт данных из FBR, поэтому в примере кода используется команда прямого ввода-вывода (CMD52), которая предписывает карта передавать запрошенные данные через строку CMD, а не строки DAT. В примере кода указывается прямая команда ввода-вывода путем присвоения этому элементу значения SDCMD_IO_RW_DIRECT.

    SD_COMMAND_CLASS

    Операции чтения относятся к стандартному набору команд (коды команд от 0 до 63), поэтому значение, присвоенное этому члену дескриптора, SDCC_STANDARD.

    SD_TRANSFER_DIRECTION

    Операции чтения требуют передачи с устройства на узел, поэтому значение, присвоенное этому члену дескриптора, равно SDTD_READ.

    SD_TRANSFER_TYPE

    Эта операция считывает небольшой объем данных из регистра через строку CMD. Карта не нужно отправлять данные по строкам DAT, поэтому этому члену присваивается значение SDTT_CMD_ONLY.

    SD_RESPONSE_TYPE

    Дескриптор задает тип ответа SDRT_5, что означает, что карта должен уведомить узел о завершении операции с помощью запроса прерывания. Описание ответа R5 см. в спецификации Сопоставления карт MultiMedia .

  2. Инициализируйте пакет запроса , выполнив следующие действия.

    1. Определите функцию запроса:

      После создания дескриптора SD в примере кода инициализируется пакет запроса , SDBUS_REQUEST_PACKET. Элемент RequestFunction пакета запроса указывает, содержит ли запрос команду устройства (значение SDRF_DEVICE_COMMAND) или операцию свойства (значение SDRF_GET_PROPERTY или SDRF_SET_PROPERTY). В примере кода инициируется команда устройства, поэтому члену RequestFunction присваивается значение SDRF_DEVICE_COMMAND.

    2. Загрузка дескриптора команд. Далее в примере кода новый инициализированный дескриптор сохраняется в элементе Parameters.DeviceCommand.CmdDesc пакета запроса.

    3. Инициализируйте аргумент чтения и записи:

      Пакет запроса содержит структуру SD_RW_DIRECT_ARGUMENT , содержащую расположение данных, извлекаемых драйвером шины. В этой структуре также хранится количество функции, пространство ввода-вывода которой считывает водитель автобуса. Пример кода извлекает номер функции из расширения устройства, что означает, что драйвер ранее извлек сведения из карта (вероятно, при запуске устройства) с помощью запроса SDRF_GET_PROPERTY и сохранил их в расширении устройства.

  3. Отправка запроса

    После инициализации дескриптора и пакета запроса для отправки запроса в примере кода используется синхронная подпрограмма запроса SdBusSubmitRequest. Подпрограмма запроса передает пакет запроса и сведения о контексте интерфейса, которые система предоставила драйверу при открытии интерфейса SD. Так как это синхронный запрос, драйвер должен работать в IRQL менее DISPATCH_LEVEL.

  4. Результаты выполнения команды

    Так как в примере кода используется прямой ввод-вывод, буфер данных не требуется, кроме поля ResponseData в пакете запроса SD.