Condividi tramite


Sviluppare moduli di estendibilità del trasporto KDNET

Questo argomento descrive in che modo il trasporto KDNET può essere esteso per l'esecuzione su qualsiasi hardware tramite l'uso di una DLL del modulo di estendibilità del driver hardware separato. I moduli di estendibilità del trasporto KDNET vengono sviluppati dai fornitori di schede di rete per aggiungere il supporto del debug del kernel a schede di rete specifiche.

Panoramica di KDNET

KDNET è un trasporto di debug del kernel che consente il debug del kernel di windows in rete. Inizialmente è stato usato per supportare il debug del kernel con schede di interfaccia di rete Ethernet. È progettato in modo che il livello di supporto hardware sia integrato in un modulo separato dal livello di elaborazione dei pacchetti di rete e dell'interfaccia kernel. Questo livello di supporto del driver hardware è denominato modulo di estendibilità KDNET.

KDNET è l'unico trasporto che può essere esteso per l'esecuzione su qualsiasi hardware tramite l'uso di una DLL del modulo di estendibilità del driver hardware separato. È l'obiettivo di supportare tutto il debug di Windows tramite moduli di estendibilità KDNET e KDNET. Tutte le altre DLL di trasporto del kernel (kdcom.dll, kd1394.dll, kdusb.dll e così via) verranno deprecate e rimosse da Windows.

Esistono due tipi di interfacce usate da KDNET per comunicare con i moduli di estendibilità KDNET. Uno è un'interfaccia basata su pacchetti usata per schede di interfaccia di rete, USB e hardware wireless e l'altra è un'interfaccia basata su byte usata per supportare KDNET su hardware seriale.

I moduli di estendibilità KDNET devono rispettare requisiti molto rigorosi per funzionare correttamente. Poiché vengono usati per il debug del kernel, verranno chiamati ed eseguiti quando il sistema sta bloccando un'ulteriore esecuzione del codice. In genere, tutti i processori del sistema vengono bloccati in un IPI, ad eccezione del processore che comunica con l'applicazione debugger in esecuzione nel computer host tramite il trasporto di debug del kernel. Il processore è in genere in esecuzione con interrupt completamente disabilitato ed è essenzialmente in esecuzione sull'hardware del trasporto di debug in attesa che i comandi provengano dal debugger.

Importare ed esportare

I moduli di estendibilità KDNET hanno esattamente un'esportazione esplicita: KdInitializeLibrary. Non hanno anche importazioni esplicite. I moduli di estendibilità KDNET vengono passati un puntatore a una struttura con un elenco delle routine a cui è consentito chiamare da KDNET quando chiama KdInitializeLibrary. Non è possibile chiamare altre routine. Periodo. I moduli di estendibilità KDNET con importazioni non sono progettati correttamente e non saranno supportati.

Se si esegue il dump delle importazioni e delle esportazioni di moduli di estendibilità KDNET usando il collegamento /dump /export e il collegamento /dump /imports, si noterà che hanno una sola esportazione (KdInitializeLibrary) e nessuna importazione. I moduli di estendibilità KDNET segnalano le esportazioni aggiuntive in KDNET inserendo puntatori a funzioni in una struttura di funzioni di esportazione in cui KDNET passa un puntatore quando viene chiamato KdInitializeLibrary. KDNET usa quindi i puntatori a funzione in tale struttura per chiamare nel modulo di estendibilità ed eseguire trasferimenti di dati usando l'hardware supportato dal modulo. KDNET determina se il modulo è un modulo basato su pacchetti o byte esaminando le funzioni specifiche compilate dal modulo nella tabella delle funzioni di esportazione nella struttura. Alcune di queste funzioni sono per supportare l'hardware basato su pacchetti e altre sono per l'hardware basato su seriale. Alcune delle funzioni della tabella vengono usate sia dall'hardware seriale che da quello basato su pacchetti (KdInitializeController, KdShutdownController, KdGetHardwareContextSize).

Progettazione del codice

I moduli di estendibilità KDNET devono essere scritti come codice a thread singolo. Non devono eseguire alcuna sincronizzazione. Tutti i trasporti di debug del kernel dipendono dal kernel di Windows per eseguire la sincronizzazione corretta quando viene immesso il debugger. Il kernel ha un blocco del debugger che richiede quando entra nel debugger del kernel e blocca anche gli altri processori nel sistema in un IPI quando viene immesso il debugger. Tali processori verranno rilasciati, solo quando il debugger del kernel in esecuzione nell'host indica al computer di destinazione di consentire l'esecuzione per continuare. Poiché il kernel esegue questa sincronizzazione, i moduli di estendibilità KDNET non devono assolutamente usare spinlock, mutex, gate o qualsiasi altro meccanismo di sincronizzazione di Windows nel codice. Devono essere scritti per programmare direttamente il rispettivo hardware per inviare e ricevere pacchetti e byte.

Il codice del modulo di estendibilità KDNET deve essere reso il più semplice possibile. In questo modo si garantisce che sia il più possibile privo di bug, poiché il debug del codice del modulo di estendibilità KDNET in un computer non è attualmente possibile senza l'uso di un debugger hardware. Non è possibile usare il debugger del kernel per eseguire il debug del codice di trasporto del kernel. Il tentativo di eseguire questa operazione causerà il riavvio del computer a causa di uno stack di kernel soffiato (che in genere termina con un doppio errore e riavvio) o un deadlock, o causerà l'inserimento del trasporto, che nella maggior parte dei casi causerà il mancato funzionamento del trasporto.

Convenzioni di denominazione dei moduli di estendibilità KDNET

Il modulo di trasporto di debug del kernel deve seguire una delle due convenzioni di denominazione per i moduli di estendibilità KDNET. Se il modulo è per supportare l'hardware basato su PCI, deve essere denominato kd_YY_XXXX.dll dove XXXX è l'ID fornitore PCI dell'hardware in esadecimale e YY è la classe PCI per l'hardware. Sono disponibili diversi moduli di estendibilità KDNET inclusi nella casella nelle finestre che supportano l'hardware basato su PCI. Ad esempio, i kd_02_8086.dll intel, i kd_02_14e4.dll di Broadcom e i kd_02_10ec.dll di Realtek. È possibile cercare gli ID fornitore PCI registrati in https://www.pcisig.com/membership/member-companies Tutti i moduli di estendibilità KDNET basati su PCI usano il VID fornitore dell'hardware supportato nell'esadecimale come ultimi 4 caratteri nel nome del modulo. Il codice di classe per la maggior parte dei moduli box è 02, perché sono dispositivi di classe di rete e pertanto hanno una classe PCI di 0x02 nello spazio di configurazione PCI. Winload.exe compila il nome dei moduli di estendibilità KDNET basati su PCI leggendo la classe di dispositivo PCI e il VID PCI del dispositivo di debug selezionato dallo spazio di configurazione PCI e tenta di caricare un modulo con tali identificatori nel nome. Se il dispositivo ha un codice di classe PCI che non è la classe di 0x02 di rete, è necessario usare il codice di classe PCI corretto in esadecimale per il dispositivo, nel nome del modulo di estendibilità KDNET. In caso contrario, il modulo non verrà caricato correttamente tramite winload. _02_ in ognuno di questi nomi è il codice di classe PCI per i dispositivi della classe di rete in esadecimale. Questo codice viene trovato e letto anche dallo spazio di configurazione PCI del dispositivo di debug.

Se si dispone di un dispositivo con una voce di tabella DBG2 e non è un dispositivo basato su PCI, la convenzione di denominazione per il modulo è diversa. La convenzione di denominazione per i dispositivi di debug delle tabelle DBG2 è kd_XXXX_YYYY.dll dove XXXX è la tabella DBG2 esadecimale PortType e YYYY è la tabella DBG2 esadecimale PortSubtype dalla voce della tabella DBG2. Kd_8003_5143.dll è una DLL posta in arrivo per supportare un portType net (0x8003) con un sottotipo di 0x5143. In questo caso 5143 è qualcomm PCI vid, poiché si tratta del supporto KDNET nei controller USB Qualcomm e per le voci della tabella Net DBG2 il PortSubtype è definito come PCI VID per il fornitore dell'hardware. Si noti che è possibile supportare dispositivi seriali, USB e altri dispositivi di tabella DBG2 usando questa convenzione di denominazione. Di seguito sono riportati i valori PortType attualmente supportati in hex: 8000 per i dispositivi seriali, 8001 per dispositivi 1394, 8002 per dispositivi USB, 8003 per dispositivi NET. Si noti che i sottotipi per i dispositivi seriali e USB devono essere riservati con Microsoft. Microsoft gestisce un elenco dei sottotipi seriali e USB allocati. Inviare un messaggio di posta elettronica a per riservare kdnet@microsoft.com un sottotipo seriale o USB, se i tipi supportati esistenti non funzioneranno con l'hardware.

Importazioni di estendibilità KDNET

Di seguito è riportato l'elenco delle routine che è possibile chiamare da un modulo di estendibilità KDNET. Si noti che tutte queste routine vengono passate alla routine KdInitializeLibrary e l'intestazione kdnetextensibility.h eseguirà il mapping delle normali chiamate a queste routine per passare attraverso la tabella di importazione. Il codice deve chiamarli tramite la tabella di importazione, in modo che il modulo non abbia importazioni. Non è possibile chiamare altre routine esportate dal kernel, dall'HAL o da qualsiasi altro modulo del kernel. È possibile chiamare solo queste routine. Questo set di routine si è dimostrato sufficiente per sviluppare tutti i moduli di estendibilità KDNET box e dovrebbe essere sufficiente per gli scenari normali. Se sono necessarie routine aggiuntive esportate dal kernel, ma non in questo elenco, inviare un messaggio di posta elettronica per kdnet@microsoft.com spiegare lo scenario e quali routine aggiuntive sono necessarie e perché. Tieni presente che questo elenco verrà aggiunto solo ai cicli di rilascio principali di Windows, se affatto. Si noti che la maggior parte di queste routine corrisponde direttamente alle API del kernel di Windows supportate dal kernel o da HAL. Una o due sono routine personalizzate solo KDNET.

È fondamentale includere kdnetextensibility.h correttamente nelle intestazioni in modo che possa verificarsi il mapping corretto delle routine tramite la tabella di importazione. In caso contrario, il modulo avrà importazioni e non sarà supportato.

Letture delle routine di memoria di scrittura

Le routine seguenti devono essere usate per la lettura e la scrittura nella memoria mappata alla memoria del dispositivo. Queste hanno la stessa convenzione di chiamata e vengono mappate alle routine del kernel corrispondenti: READ_REGISTER_UCHAR, READ_REGISTER_USHORT, READ_REGISTER_ULONG, WRITE_REGISTER_UCHAR, WRITE_REGISTER_USHORT, WRITE_REGISTER_ULONG e su piattaforme a 64 bit solo READ_REGISTER_ULONG64 e WRITE_REGISTER_ULONG64. Tutti gli accessi alla memoria del dispositivo devono essere eseguiti tramite queste routine, in quanto assicurano che le letture e le scritture non vengano riordinate dal processore. Si noti che il msdn.microsoft.com documenta routine di Windows CE Compact 2013 che corrispondono alla convenzione di chiamata a queste routine. Purtroppo sembra che le routine NT non siano documentate, ma la convenzione di chiamata è la stessa.

Leggere le routine delle porte di I/O

Le routine seguenti devono essere usate per la lettura e la scrittura nelle porte di I/O del dispositivo. Hanno la stessa convenzione di chiamata e vengono mappati alle routine del kernel corrispondenti: READ_PORT_UCHAR, READ_PORT_USHORT, READ_PORT_ULONG, WRITE_PORT_UCHAR, WRITE_PORT_USHORT e WRITE_PORT_ULONG. Tutte le porte di I/O del dispositivo devono essere eseguite tramite queste routine. Si noti che il msdn.microsoft.com documenta routine di Windows CE Compact 2013 che corrispondono alla convenzione di chiamata a queste routine.

Routine aggiuntive

È possibile chiamare le routine aggiuntive seguenti e deve essere chiamata normalmente con i parametri specificati. Si noti che in questo modo, includendo correttamente l'intestazione kdnetextensibility.h, eseguirà il mapping delle chiamate di funzione tramite la tabella di importazione dell'estendibilità KDNET, con conseguente assenza di importazioni esplicite nel modulo, come richiesto per i moduli di estendibilità KDNET.

PHYSICAL_ADDRESS

KdGetPhysicalAddress (

    __in PVOID Va

    );
 

VOID

KeStallExecutionProcessor (

    __in ULONG Microseconds

    );


ULONG

KdGetPciDataByOffset (

    __in ULONG BusNumber,

    __in ULONG SlotNumber,

    __out_bcount(Length) PVOID Buffer,

    __in ULONG Offset,

    __in ULONG Length

    );
 

ULONG

KdSetPciDataByOffset (

    __in ULONG BusNumber,

    __in ULONG SlotNumber,

    __in_bcount(Length) PVOID Buffer,

    __in ULONG Offset,

    __in ULONG Length

    );

 
VOID

KdSetDebuggerNotPresent (

    __in BOOLEAN NotPresent

    );
 

VOID

PoSetHiberRange (

    _In_opt_ PVOID MemoryMap,

    _In_ ULONG     Flags,

    _In_ PVOID     Address,

    _In_ ULONG_PTR Length,

    _In_ ULONG     Tag

    );

 

VOID

KeBugCheckEx (

    __in ULONG BugCheckCode,

    __in ULONG_PTR BugCheckParameter1,

    __in ULONG_PTR BugCheckParameter2,

    __in ULONG_PTR BugCheckParameter3,

    __in ULONG_PTR BugCheckParameter4

    );


PVOID

KdMapPhysicalMemory64 (

    _In_ PHYSICAL_ADDRESS PhysicalAddress,

    _In_ ULONG NumberPages,

    _In_ BOOLEAN FlushCurrentTLB

    );
 

VOID

KdUnmapVirtualAddress (

    _In_ PVOID VirtualAddress,

    _In_ ULONG NumberPages,

    _In_ BOOLEAN FlushCurrentTLB

    );
 

ULONG64

KdReadCycleCounter (

    __out_opt PULONG64 Frequency

    );

Si noti che la funzione PoSetHiberRange deve essere chiamata solo dalla routine KdSetHibernateRange. Inoltre, la maggior parte dei moduli di estendibilità KDNET non deve chiamare KeBugCheckEx, KdMapPhysicalMemory64 e KdUnmapVirtualAddress. D'altra parte essenzialmente tutti i moduli di estendibilità KDNET dovranno chiamare KdGetPhysicalAddress per ottenere gli indirizzi di memoria fisica necessari per programmare i motori DMA del dispositivo e molti dovranno chiamare KeStallExecutionProcessor, KdGetPciDataByOffset e KdSetPciDataByOffset. Le ultime due routine sono destinate all'accesso allo spazio di configurazione PCI del dispositivo.

Esportazioni di estendibilità KDNET

Di seguito è riportata una breve descrizione di ognuna delle routine di estendibilità KDNET. È necessario implementare tutte le routine necessarie per un modulo di estendibilità KDNET basato su pacchetti o per un modulo di estendibilità KDNET basato su seriale. Di seguito sono riportate le esportazioni del modulo di estendibilità KDNET dei pacchetti.

KdInitializeLibrary

/*++

Routine Description:

    This routine validates that the ImportTable is a supported version.  Makes
    a copy of the ImportTable in its own global memory, and writes pointers to
    functions that it exports into the Exports pointer also located in that
    table.

    This routine also writes the size in bytes of the Memory it needs into
    the Length field of the Memory structure contained in the debug device
    descriptor passed to this routine.

    When kernel debugging is enabled, this routine will be called twice during
    boot.  The first time by winload to determine how much memory to allocate
    for KDNET and its extensibility module, and the second time by KDNET when
    the kernel first initializes the kernel debugging subsystem.

Arguments:

    ImportTable - Supplies a pointer to the KDNET_EXTENSIBILITY_IMPORT
        structure.

    LoaderOptions - Supplies a pointer to the LoaderOptions passed to the
        kernel.  This allows settings to be passed to the KDNET extensibility
        module using the loadoptions BCD setting.

    Device - Supplies a pointer to the debug device descriptor.

Return Value:

    STATUS_INVALID_PARAMETER if the version of the import or export table is
        incorrect.

    STATUS_SUCCESS if initialization succeeds.

--*/
NTSTATUS
KdInitializeLibrary (
    __in PKDNET_EXTENSIBILITY_IMPORTS ImportTable,
    __in_opt PCHAR LoaderOptions,
    __inout PDEBUG_DEVICE_DESCRIPTOR Device
    )
{
    NTSTATUS Status;
    PKDNET_EXTENSIBILITY_EXPORTS Exports;

    __security_init_cookie();
    Status = STATUS_SUCCESS;
    KdNetExtensibilityImports = ImportTable;
    if ((KdNetExtensibilityImports == NULL) ||
        (KdNetExtensibilityImports->FunctionCount != KDNET_EXT_IMPORTS)) {

        Status = STATUS_INVALID_PARAMETER;
        goto KdInitializeLibraryEnd;
    }

    Exports = KdNetExtensibilityImports->Exports;
    if ((Exports == NULL) || (Exports->FunctionCount != KDNET_EXT_EXPORTS)) {
        Status = STATUS_INVALID_PARAMETER;
        goto KdInitializeLibraryEnd;
    }

    //
    // Return the function pointers this KDNET extensibility module exports.
    //

    Exports->KdInitializeController = KdInitializeController;
    Exports->KdShutdownController = KdShutdownController;
    Exports->KdSetHibernateRange = KdSetHibernateRange;
    Exports->KdGetRxPacket = KdGetRxPacket;
    Exports->KdReleaseRxPacket = KdReleaseRxPacket;
    Exports->KdGetTxPacket = KdGetTxPacket;
    Exports->KdSendTxPacket = KdSendTxPacket;
    Exports->KdGetPacketAddress = KdGetPacketAddress;
    Exports->KdGetPacketLength = KdGetPacketLength;
    Exports->KdGetHardwareContextSize = KdGetHardwareContextSize;

    //
    // Return the hardware context size required to support this device.
    //

    Status = ContosoInitializeLibrary(LoaderOptions, Device);

KdInitializeLibraryEnd:
    return Status;
}

Questa routine viene chiamata per passare le routine di importazione ed esportazione tra KDNET e questo modulo di estendibilità KDNET. Questa routine deve verificare che la versione delle tabelle di importazione ed esportazione sia prevista e supportata e che non riesca in caso contrario. Deve creare una copia della tabella di importazione nella propria memoria globale. Deve scrivere le routine esportate nella struttura a cui punta il campo Esporta della tabella di importazione. Deve anche impostare il campo Lunghezza della struttura Memoria che fa parte del puntatore del descrittore del dispositivo di debug passato a questa routine, con il numero di byte di memoria che richiede per supportare il dispositivo hardware.

Convalidare il conteggio delle esportazioni di importazione

Il codice deve verificare che Imports FunctionCount corrisponda a ciò che è disponibile nel sistema operativo, ad esempio , (KdNetExtensibilityImports->FunctionCount != KDNET_EXT_IMPORTS) e restituire STATUS_INVALID_PARAMETER se il conteggio non corrisponde.

Il controllo dei conteggi garantisce la compatibilità tra la versione KDNET del sistema operativo Windows in esecuzione (ad esempio, gestore di avvio/caricatore/hypervisor/kernel/sistema operativo SICURO/SISTEMA operativo NT, tutti collegati alla libreria KDNET) e la versione WDK usata per compilare il modulo di estendibilità KDNET corrente. Il wdk e la versione del sistema operativo devono essere sincronizzati; in caso contrario, il controllo precedente avrà esito negativo se il valore del contatore di importazione/esportazione cambia. Ad esempio, se l'interfaccia di estendibilità KDNET ha aggiunto una nuova funzione di funzionalità, il conteggio non corrisponderà più. Per assicurarsi che corrispondano, usare sempre la versione WDK corrispondente al sistema operativo che ospita la versione KDNET.

Personalizzare la memoria necessaria

Si noti che il dispositivo verrà popolato con l'hardware selezionato per il debugger. Questa routine deve personalizzare la quantità di memoria necessaria in base al dispositivo, se necessario. Ad esempio, i moduli di estendibilità che supportano hardware 1Gig e 10Gig possono aumentare le dimensioni di memoria richieste per i dispositivi 10Gig. Possono determinare quale dispositivo viene usato esaminando il campo DeviceID del descrittore del dispositivo di debug.

KdInitializeLibrary è l'unica esportazione

Si noti che questa routine verrà chiamata sia da winload che da KDNET durante la chiamata KdInitSystem. Si noti che si tratta della routine ONLY esportata dai moduli di estendibilità KDNET. È l'unica routine inserita in un file con estensione def. I moduli di estendibilità KDNET hanno esattamente un'esportazione esplicita, questa routine, e nessuna importazione.

KdSetHibernateRange

VOID

KdSetHibernateRange (

    VOID

    )

/*++
Routine Description:

    This routine is called to mark the code in the KDNET extensiblity module
    so that it can be properly handled during hibernate and resume from
    hibernate.

Arguments:
    None.

Return Value:
    None.
--*/

Questa routine viene chiamata dal sistema prima dell'ibernazione in modo che possa registrare correttamente il codice usato dal modulo di estendibilità KDNET con il sistema. Ciò consente al sistema di gestire correttamente la memoria durante l'ibernazione e riprendere dall'ibernazione. (La memoria viene salvata in ritardo e caricata in anticipo, poiché verrà chiamata molto presto durante la ripresa).

KdInitializeController

NTSTATUS

KdInitializeController(

    __in PVOID Adapter

    )

/*++
Routine Description:

    This function initializes the Network controller.  The controller is setup
    to send and recieve packets at the fastest rate supported by the hardware
    link.  Packet send and receive will be functional on successful exit of
    this routine.  The controller will be initialized with Interrupts masked
    since all debug devices must operate without interrupt support.

Arguments:

    Adapter - Supplies a pointer to the debug adapter object.

Return Value:
    STATUS_SUCCESS on successful initialization.  Appropriate failure code if
    initialization fails.
--*/

Questa routine viene chiamata per inizializzare l'hardware. Viene chiamato quando il sistema viene inizializzato e ogni volta che il sistema viene riattivato da uno stato di basso consumo per il quale ha chiamato KdShutdownController. Questa routine DEVE assicurarsi che l'hardware abbia completato completamente l'inizializzazione e che sia pronto per l'invio di pacchetti PRIMA della restituzione. Questa routine dovrebbe attendere che il PHY venga visualizzato e che il collegamento venga stabilito. Si noti che se non è presente alcun cavo collegato, questa routine non dovrebbe bloccarsi a tempo indeterminato. Questa routine imposta la velocità del collegamento e il duplex nella struttura di dati condivisi KDNET condivisa tra KDNET e questo modulo di estendibilità. Scrive anche l'indirizzo MAC usato dall'hardware, nella posizione a cui punta TargetMacAddress nella struttura dei dati condivisi KDNET.

KdShutdownController

VOID

KdShutdownController (

    __in PVOID Adapter

    )

/*++
Routine Description:

    This function shuts down the Network controller.  No further packets can
    be sent or received until the controller is reinitialized.

Arguments:

    Adapter - Supplies a pointer to the debug adapter object.

Return Value:

    None.
--*/

È FONDAMENTALE che questa routine ATTENDA fino a quando tutti i pacchetti che ancora in sospeso vengono effettivamente inviati in rete. Questa routine deve attendere fino a quando tutti i pacchetti di trasmissione sono stati DMA'ed dalla memoria principale e sono in transito PRIMA che arresti la trasmissione sull'hardware. Una volta inviati tutti i pacchetti di trasmissione in sospeso, questa routine dovrebbe arrestare completamente l'hardware. Questa routine verrà chiamata quando il sistema si arresta e anche quando il sistema decide di gestire il trasporto di debug a uno stato a basso consumo. Questo può essere chiamato quando il sistema entra in standby, ibernazione, sospensione e standby connesso, oltre a quando il sistema è arrestato.

KdGetHardwareContextSize

ULONG

KdGetHardwareContextSize (

    __in PDEBUG_DEVICE_DESCRIPTOR Device

    )
 

/*++
Routine Description:

    This function returns the required size of the hardware context in bytes.

Arguments:

    Device - Supplies a pointer to the debug device descriptor.

Return Value:

    None.

--*/

Questa routine deve restituire il numero di byte necessari per tutta la memoria necessaria per supportare l'hardware. Sono inclusi la struttura del contesto e tutti i buffer di pacchetti per la ricezione e la trasmissione, nonché i descrittori di pacchetti hardware e altre strutture. Le dimensioni di TUTTA la memoria necessaria devono essere segnalate qui. L'inclusione di qualsiasi memoria aggiuntiva necessaria per le limitazioni di allineamento dell'hardware potrebbe avere per pacchetti o descrittori di pacchetti o altre strutture.

Si noti che questa routine deve essere chiamata dalla routine KdInitializeLibrary quando imposta il campo Lunghezza memoria nel descrittore del dispositivo di debug.

KdGetRxPacket

NTSTATUS

KdGetRxPacket (

    __in PVOID Adapter,

    __out PULONG Handle,

    __out PVOID *Packet,

    __out PULONG Length

)

/*++

Routine Description:

    This function returns the next available received packet to the caller.

Arguments:

    Adapter - Supplies a pointer to the debug adapter object.

    Handle - Supplies a pointer to the handle for this packet.  This handle
        will be used to release the resources associated with this packet back
        to the hardware.

    Packet - Supplies a pointer that will be written with the address of the
        start of the packet.

    Length - Supplies a pointer that will be written with the length of the
        received packet.

Return Value:

    STATUS_SUCCESS when a packet has been received.
    STATUS_IO_TIMEOUT otherwise.

--*/

Questa routine ottiene il pacchetto disponibile successivo ricevuto, ma non ancora elaborato. Restituisce un handle per il pacchetto. L'handle verrà usato per ottenere l'indirizzo del pacchetto chiamando KdGetPacketAddress, nonché la lunghezza chiamando KdGetPacketLength. Il pacchetto e l'handle devono rimanere disponibili e validi fino a quando il pacchetto non viene rilasciato chiamando KdReleaseRxPacket. Questa routine restituisce direttamente anche l'indirizzo e la lunghezza del pacchetto al chiamante.

Se non è attualmente disponibile, questa routine DEVE restituire immediatamente con STATUS_IO_TIMEOUT. Questa routine NON DEVE attendere la ricezione di un pacchetto. Si noti che i primi 2 bit di Handle sono riservati. TRANSMIT_HANDLE e TRANSMIT_ASYNC devono essere chiari.

KdReleaseRxPacket

VOID

KdReleaseRxPacket (

    __in PVOID Adapter,

    ULONG Handle

)

/*++

Routine Description:

    This function reclaims the hardware resources used for the packet
    associated with the passed Handle.  It reprograms the hardware to use those
    resources to receive another packet.

Arguments:

    Adapter - Supplies a pointer to the debug adapter object.
    Handle - Supplies the handle of the packet whose resources should be
        reclaimed to receive another packet.

Return Value:

    None.

--*/

Questa routine rilascia le risorse associate all'handle di pacchetto all'hardware in modo che possano essere usate per ricevere un altro pacchetto. Ogni chiamata a KdGetRxPacket che ha esito positivo verrà seguita da un'altra chiamata a KdReleaseRxPacket con l'handle restituito da KdGetRxPacket. Si noti che NON è garantito che KdReleaseRxPacket verrà chiamato immediatamente dopo l'esito positivo di KdGetRxPacket. È possibile che venga effettuata un'altra chiamata KdGetRxPacket. Tuttavia, ogni chiamata KdGetRxPacket riuscita avrà le relative risorse rilasciate con una chiamata KdReleaseRxPacket.

Questa routine deve programmare correttamente l'hardware in modo che le risorse rilasciate possano essere usate per ricevere un altro pacchetto.

KdGetTxPacket

NTSTATUS

KdGetTxPacket (

    __in PVOID Adapter,

    __out PULONG Handle

)

/*++

Routine Description:

    This function acquires the hardware resources needed to send a packet and
    returns a handle to those resources.

Arguments:

    Adapter - Supplies a pointer to the debug adapter object.

    Handle - Supplies a pointer to the handle for the packet for which hardware
        resources have been reserved.

Return Value:

    STATUS_SUCCESS when hardware resources have been successfully reserved.
    STATUS_IO_TIMEOUT if the hardware resources could not be reserved.
    STATUS_INVALID_PARAMETER if an invalid Handle pointer or Adapter is passed.

--*/

Questa routine ottiene le risorse di trasmissione disponibili successive e restituisce un handle. Questo handle verrà usato per chiamare KdGetPacketAddress e KdGetPacketLength. L'indirizzo del pacchetto restituito da KdGetPacketAddress verrà usato per scrivere direttamente il contenuto del pacchetto. L'indirizzo del pacchetto deve essere l'inizio del pacchetto e la lunghezza deve essere il numero massimo di byte che è possibile scrivere nel pacchetto. Si noti che se non sono disponibili risorse hardware, perché sono state acquisite tutte e non sono ancora state trasmesse, questa routine dovrebbe restituire immediatamente STATUS_IO_TIMEOUT.

TRANSMIT_HANDLE deve essere impostato nell'handle restituito. Si noti che i due bit principali di Handle sono riservati per i flag TRANSMIT_ASYNC e TRANSMIT_HANDLE.

KdSendTxPacket

NTSTATUS

KdSendTxPacket (

    __in PVOID Adapter,

    ULONG Handle,

    ULONG Length

)

/*++

Routine Description:

    This function sends the packet associated with the passed Handle out to the
    network.  It does not return until the packet has been sent.

Arguments:

    Adapter - Supplies a pointer to the debug adapter object.

    Handle - Supplies the handle of the packet to send.

    Length - Supplies the length of the packet to send.

Return Value:

    STATUS_SUCCESS when a packet has been successfully sent.

    STATUS_IO_TIMEOUT if the packet could not be sent within 100ms.

    STATUS_INVALID_PARAMETER if an invalid Handle or Adapter is passed.

--*/

Questa routine invia il pacchetto associato all'handle passato in rete. Si noti che Handle può avere un bit aggiuntivo impostato in esso, che indica se l'invio è un trasferimento asincrono o meno. Se il flag TRANSMIT_ASYNC è impostato nell'handle, questa routine deve programmare l'hardware per inviare il pacchetto e quindi restituire immediatamente senza attendere il completamento dell'invio dell'hardware. Ciò significa che tutti gli errori che si verificano durante la trasmissione andranno persi. Va bene, e per impostazione predefinita, poiché i pacchetti possono essere persi in transito comunque. Se il flag TRANSMIT_ASYNC non è impostato nell'handle, questa routine DEVE attendere fino a quando il pacchetto non è stato inviato in rete e deve restituire qualsiasi errore che si verifica durante la trasmissione, se presente. Si noti che quando i file di dump vengono inviati all'host del debugger o quando i pacchetti di rete di Windows vengono inviati da KDNIC tramite KDNET, verrà impostato TRANSMIT_ASYNC. Quando tutti gli altri pacchetti del debugger vengono inviati TRANSMIT_ASYNC sarà chiaro.

Se un set di pacchetti viene inviato con TRANSMIT_ASYNC set TRUE, seguito da un pacchetto che non ha TRANSMIT_ASYNC impostato, l'hardware deve attendere fino a quando il pacchetto senza il set di flag viene effettivamente inviato, anche se ciò significa che deve attendere l'invio anche dei pacchetti asincroni precedenti.

KdGetPacketAddress

PVOID

KdGetPacketAddress (

    __in PVOID Adapter,

    ULONG Handle

)

/*++

Routine Description:

    This function returns a pointer to the first byte of a packet associated
    with the passed handle.

Arguments:

    Adapter - Supplies a pointer to the debug adapter object.

    Handle - Supplies a handle to the packet for which to return the
        starting address.

Return Value:

    Pointer to the first byte of the packet.

--*/

Questa routine restituisce un puntatore al primo byte del pacchetto associato all'handle passato. Si noti che l'handle avrà il bit TRANSMIT_HANDLE impostato per i pacchetti di trasmissione e il bit TRANSMIT_HANDLE chiaro per i pacchetti di ricezione. Il puntatore restituito deve essere un indirizzo virtuale Windows che può essere letto o scritto dal processore. Questo indirizzo deve rientrare nel blocco di memoria riservato per il modulo di estendibilità KDNET passato nella struttura memory del descrittore del dispositivo di debug. Si noti che il modulo di estendibilità KDNET non deve mai usare più delle dimensioni di memoria richieste in KdInitializeLibrary durante l'accesso a tale memoria. Qualsiasi memoria aggiuntiva alla fine del blocco è riservata per l'uso da KDNET e non deve essere toccato dal modulo di estendibilità KDNET.

KdGetPacketLength

ULONG

KdGetPacketLength (

    __in PVOID Adapter,

    ULONG Handle

)

/*++

Routine Description:

    This function returns the length of the packet associated with the passed
    handle.

Arguments:

    Adapter - Supplies a pointer to the debug adapter object.

    Handle - Supplies a handle to the packet for which to return the
        length.

Return Value:

    The length of the packet.

--*/

Questa routine restituisce una lunghezza in byte del pacchetto associato all'handle passato. Si noti che l'handle avrà il bit TRANSMIT_HANDLE impostato per i pacchetti di trasmissione e il bit TRANSMIT_HANDLE chiaro per i pacchetti di ricezione. Per i pacchetti di trasmissione, questa lunghezza deve essere il numero massimo di byte che possono essere scritti nel pacchetto. Per i pacchetti di ricezione, questa lunghezza deve essere il numero effettivo di byte nel pacchetto ricevuto.

Debug di moduli di estendibilità KDNET

Per eseguire il debug di un modulo di estendibilità KDNET, è necessario eseguire i comandi bcdedit seguenti da un prompt dei comandi con privilegi elevati nel computer di destinazione.

In primo luogo, e più importante, è necessario eseguire i due comandi seguenti per assicurarsi che Winload consentirà errori di avvio ripetuti senza arrestare un percorso di errore speciale che si interrompe nel debugger e impedisce l'avvio normale. L'esecuzione di questi comandi consentirà di riavviare ripetutamente il computer con nuovi bit ed eseguire il debug di questi nuovi bit senza problemi.

Bcdedit -set {current} BootStatusPolicy IgnoreAllFailures

Bcdedit -set {current} RecoveryEnabled No

Supponendo di usare il debug seriale in com1 nel computer di destinazione per eseguire il debug del modulo di estendibilità, eseguire le operazioni seguenti.

bcdedit -dbgsettings serial debugport:1 baudrate:115200

In questo modo il trasporto di debug predefinito viene serializzato su com1 a 115200 baud. Queste impostazioni verranno usate anche per il debug di avvio.

bcdedit -debug on

In questo modo è possibile eseguire il debug del kernel.

bcdedit -bootdebug on

Ciò consente il debug di avvio in winload.exe, che verrà usato per eseguire il debug nell'inizializzazione iniziale del kernel, incluso il modulo di estendibilità KDNET.

bcdedit -set kerneldebugtype net

In questo modo il tipo di debug del kernel viene impostato su net, indipendentemente dalle impostazioni di trasporto di debug predefinite. In questo modo winload.exe caricare kdnet.dll come trasporto di debug del kernel.

bcdedit -set kernelbusparams b.d.f

Dove b è il numero dell'autobus, d è il numero di dispositivo e f è il numero di funzione, tutto in decimale, dell'hardware per cui si sta scrivendo il modulo di estendibilità KDNET. Questi numeri dipenderanno dallo slot PCI in cui si trova l'hardware. Puoi trovarli trovando la stringa di posizione nella pagina delle proprietà del dispositivo di rete in Gestione dispositivi Windows. Aprire Gestione dispositivi Windows, fare doppio clic sui dispositivi di rete, trovare il dispositivo, fare doppio clic su di esso e nella finestra visualizzata dovrebbe essere presente un campo Location: che contiene il bus, il dispositivo e la funzione dell'hardware nel bus PCI. Se si dispone di un autista di autobus che fa sì che tali informazioni vengano mascherate, sarà necessario determinare la posizione dei conducenti o un altro modo.

In questo modo i busparams del kernel vengono forzati a b.d.f, che forza l'opzione selezionata da quel particolare dispositivo come dispositivo di debug del kernel.

bcdedit -set kernelhostip N

Dove N è determinato dalla formula seguente. Se il computer del debugger host ha un indirizzo IPv4 w.x.y.z, N = (w0x01000000) + (x0x00010000) + (y0x00000100) + (z0x00000001). N deve essere specificato nella riga di comando in decimale, non esadecimale. In effetti si accetta ogni byte dell'indirizzo IPv4 e lo si concatena (in esadecimale) per compilare un numero a 32 bit in esadecimale e quindi convertirlo in decimale.

bcdedit -set kernelport N

Dove N è 50000 o un'altra porta che non verrà bloccata nella rete interna.

In questo modo KDNET usa la porta N come porta di debug di rete.

bcdedit -set kernelkey 1.2.3.4

In questo modo la chiave di debug KDNET viene forzata alla versione 1.2.3.4. 1.2.3.4 non è un elemento sicuro o univoco nella chiave di rete. Per proteggere il computer di destinazione, è necessario crittografare i pacchetti che si spostano tra i computer host e di destinazione. È consigliabile usare una chiave di crittografia generata automaticamente. Per altre informazioni, vedere Configurazione automatica del debug del kernel di rete KDNET.

bcdedit -set kerneldhcp on

In questo modo l'impostazione dhcp del kernel KDNET viene attivata.

Eseguire il debugger nel computer host del debugger con la riga di comando seguente presupponendo che sia in uso com1 come porta di debug seriale nel computer host:

windbg -d -k com:port=com1,baud=115200

Che eseguirà il debugger e causerà l'interruzione quando il debugger di avvio windbg comunica per la prima volta con il computer host.

Riavviare quindi il computer di destinazione eseguendo

shutdown -r -t 0

Quando il debugger si interrompe in windbg, assicurarsi di ottenere i simboli caricati per winload. Potrebbe essere necessario impostare il file con estensione sympath ed eseguire un ricaricamento. Quindi eseguire x winload!*deb*tra*. Uno dei simboli elencati sarà simile a BdDebugTransitions.

ed winload!BdDebugTransitions 1Eseguire quindi , ma assicurarsi di usare il nome del simbolo corretto.

Eseguire quindi bu winload!blbdstop per impostare un punto di interruzione.

Poi premere g per andare.

Dovresti romperti a winload! BlBdStop.

Eseguire quindi i comandi seguenti.

bu nt!KdInitSystem

bu kdnet!KdInitialize

bu kdstub!KdInitializeLibrary

Si noti che probabilmente si userà kdstub durante l'impostazione dei punti di interruzione nel modulo di estendibilità KDNET, se non funziona, usare

bu kd_YY_XXXX!KdInitializeLibrary

Dove YY è la classe PCI e XXXX è il VID PCI. (ad esempio: usare il nome del modulo di estendibilità KDNET.

In genere nel debugger è necessario usare kdstub anziché usare il nome effettivo del modulo di estendibilità.

bl Eseguire quindi per elencare i punti di interruzione. Assicurarsi che i punti di interruzione siano presenti (tutti devono avere un e accanto a essi).

Quindi premere g. Dovresti colpire il nt! Punto di interruzione KdInitSystem.

Colpisci g di nuovo, e dovresti colpire kdnet! KdInitialize

Premere g di nuovo e si dovrebbe raggiungere un punto di interruzione nel proprio modulo in KdInitializeLibrary.

È quindi possibile impostare un punto di interruzione nella routine InitializeController, nonché in tutte le altre routine ed eseguire il codice.

Dopo aver eseguito il passaggio di KdInitializeLibrary, premere g e, se si imposta un punto di interruzione nella routine InitializeController, si raggiungerà il pulsante successivo.

Al termine, assicurarsi di avere punti di interruzione impostati nelle routine KdGetTxPacket, KdSendTxPacket, KdGetRxPacket, KdReleaseRxPacket e premere di nuovo g e tali routine verranno eseguite come parte dell'inizializzazione di rete eseguita da KDNET durante l'avvio.

Potrebbe essere necessario aggiungere codice temporaneo alle routine KdInitializeLibrary o KdInitializeController per assicurarsi che tutte le routine vengano chiamate in modo da poter scorrere tutto il codice. KdShutdownController, ad esempio, non verrà chiamato durante l'avvio quando le operazioni funzionano normalmente, quindi sarà necessario chiamarlo in modo esplicito dal codice temporaneo in modo che sia possibile eseguirlo e assicurarsi che sia corretto.

Dopo aver eseguito il passaggio attraverso tutto il codice e avere la certezza che sia corretto, riavviare la destinazione, ma NON impostare il winload! BdDebugTransitions flag to true (lasciare il valore predefinito su zero).

Eseguire quindi un'altra istanza del debugger del kernel nel computer del debugger host.

Windbg -d -k net:port=50000,key=1.2.3.4

Consentire all'avvio del computer di destinazione di connettersi all'altra istanza del debugger del kernel in rete.

Eseguire quindi i comandi nel debugger del kernel e assicurarsi che funzioni, quindi lasciare che la destinazione continui l'avvio e assicurarsi che sia possibile interrompere ed eseguire i comandi in un secondo momento.

Nota

L'impostazione del flag delle transizioni di debug in winload garantisce che Windows NON VERRÀ AVVIATO. Se si tenta di consentire a Windows di completare l'avvio dopo l'impostazione di tale flag, Windows si arresterà semplicemente in modo anomalo o si blocca. Se si vuole che Windows venga avviato correttamente, non è possibile impostare il flag di transizione di debug. L'impostazione del flag consente di eseguire il debug del codice e di verificare che sia corretta, eseguendo l'istruzione all'interno del debugger, ma in ultima analisi non sarà necessario impostare il flag in modo che sia possibile verificare che il debug funzioni quando si esegue normalmente l'avvio. Ciò significa che non è possibile eseguire il codice durante l'avvio del sistema normalmente e, infatti, quando Windows è in esecuzione normalmente, con il debug abilitato nell'hardware, il modulo di estendibilità KDNET non è in grado di eseguire il debug. Qualsiasi tentativo di eseguirne il debug con il debugger del kernel causerà l'arresto anomalo del computer. Non è possibile impostare punti di interruzione nel codice che viene eseguito nei percorsi di debug del kernel, perché provoca una ripetizione infinita, uno stack soffiato e un riavvio.

Più funzioni fisiche - 2PF

Oltre all'estendibilità KDNET, KDNET supporta il debug del kernel usando più funzioni fisiche (PFS) nelle schede di interfaccia di rete supportate partizionando lo spazio di configurazione PCI. I fornitori di schede di rete sono invitati a abilitare il supporto per questa funzionalità. Per altre informazioni, vedere Debugger 2PF KDNET Miniport Network Driver Support.For more information, see Debugger 2PF KDNET Miniport Network Driver Support.

Vedi anche

Configurazione automatica del debug del kernel di rete KDNET

Configurazione manuale del debug del kernel di rete KDNET

Supporto del driver di rete miniport KDNET del debugger 2PF