Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
Topik ini menjelaskan bagaimana protokol KDNET dapat diperluas agar dapat berjalan pada perangkat keras apa pun melalui penggunaan modul perluasan driver perangkat keras terpisah dalam bentuk file DLL. Modul ekstensibilitas transport KDNET dikembangkan oleh vendor kartu jaringan untuk menambahkan dukungan debugging kernel ke kartu jaringan spesifik.
Gambaran Umum KDNET
KDNET adalah protokol debug kernel yang memungkinkan debugging kernel Windows melalui jaringan. Awalnya digunakan untuk mendukung debugging kernel dengan NIC Ethernet. Ini dirancang agar lapisan dukungan perangkat keras dibangun ke dalam modul terpisah dari pemrosesan paket jaringan dan lapisan antarmuka kernel. Lapisan dukungan driver perangkat keras ini disebut modul ekstensibilitas KDNET.
KDNET adalah satu-satunya protokol yang dapat diperluas untuk berjalan pada perangkat keras apa pun melalui penggunaan modul ekstensibilitas driver perangkat keras terpisah dalam bentuk DLL. Sasaran yang ingin dicapai adalah mendukung semua debugging Windows melalui KDNET dan modul ekstensibilitas KDNET. Semua DLL transportasi kernel lainnya (kdcom.dll, kd1394.dll, kdusb.dll, dll.) pada akhirnya akan ditolak dan dihapus dari Windows.
Ada dua jenis antarmuka yang digunakan KDNET untuk berkomunikasi dengan modul ekstensibilitas KDNET. Salah satunya adalah antarmuka berbasis paket yang digunakan untuk NIC, USB, dan perangkat keras nirkabel, dan yang lainnya adalah antarmuka berbasis byte yang digunakan untuk mendukung KDNET melalui perangkat keras serial.
Modul ekstensibilitas KDNET harus mengikuti persyaratan yang sangat ketat agar dapat beroperasi dengan benar. Karena digunakan untuk penelusuran kesalahan kernel, mereka akan dipanggil dan dijalankan ketika sistem menahan eksekusi kode lebih lanjut. Umumnya, semua prosesor dalam sistem dikunci berputar di IPI kecuali untuk prosesor yang berkomunikasi dengan aplikasi debugger yang berjalan pada komputer host melalui transportasi debug kernel. Prosesor tersebut biasanya berfungsi dengan interupsi yang sepenuhnya dinonaktifkan, dan pada dasarnya beroperasi pada perangkat keras transport debug yang menunggu instruksi dari debugger.
Impor dan ekspor
Modul ekstensibilitas KDNET memiliki persis satu ekspor eksplisit – KdInitializeLibrary. Mereka juga tidak memiliki impor eksplisit. Modul ekstensibilitas KDNET diberikan penunjuk ke struktur yang berisi daftar rutinitas yang dapat mereka panggil oleh KDNET ketika memanggil KdInitializeLibrary. Tidak ada rutinitas lain yang dapat dipanggil. Periode. Modul ekstensibilitas KDNET yang memiliki impor apa pun salah dirancang, dan tidak akan didukung.
Jika Anda membuang impor dan ekspor modul ekstensibilitas KDNET menggunakan tautan /dump /exports dan tautan /dump /imports, Anda akan melihat bahwa mereka hanya memiliki satu ekspor (KdInitializeLibrary), dan tidak ada impor. Modul ekstensi KDNET melaporkan ekspor tambahan mereka ke KDNET dengan mengisi penunjuk fungsi dalam struktur fungsi ekspor, di mana KDNET memberikan pointer saat KdInitializeLibrary dipanggil. KDNET kemudian menggunakan penunjuk fungsi dalam struktur tersebut untuk memanggil modul ekstensibilitas dan memengaruhi transfer data menggunakan perangkat keras yang didukung oleh modul. KDNET menentukan apakah modul adalah modul berbasis paket atau berbasis byte dengan melihat fungsi tertentu mana yang diisi modul dalam tabel fungsi ekspor dalam struktur. Beberapa fungsi tersebut adalah untuk mendukung perangkat keras berbasis paket, dan yang lain untuk perangkat keras berbasis serial. Beberapa fungsi dalam tabel digunakan oleh perangkat keras berbasis serial dan paket (KdInitializeController, KdShutdownController, KdGetHardwareContextSize).
Desain kode
Modul ekstensibilitas KDNET harus ditulis sebagai kode utas tunggal. Mereka tidak boleh melakukan sinkronisasi apa pun. Semua transport debug kernel bergantung pada kernel Windows untuk melakukan sinkronisasi yang tepat saat debugger dijalankan. Kernel memiliki kunci debugger yang diperlukan ketika memasuki debugger kernel, dan juga mengunci prosesor lain dalam sistem dalam IPI ketika debugger dimasukkan. Prosesor tersebut akan dirilis, hanya ketika debugger kernel yang berjalan pada host memberi tahu komputer target untuk memungkinkan eksekusi berlanjut. Karena kernel melakukan sinkronisasi ini, modul ekstensibilitas KDNET sama sekali tidak boleh menggunakan spinlock, mutex, gerbang, atau mekanisme sinkronisasi Windows lainnya dalam kode mereka. Mereka harus ditulis untuk memprogram perangkat keras masing-masing secara langsung agar dapat mengirim dan/atau menerima paket maupun byte.
Kode modul ekstensibilitas KDNET harus dibuat sesederhana mungkin. Ini akan membantu memastikan bahwa itu bebas dari bug sebanyak mungkin, karena debugging kode dari modul ekstensibilitas KDNET, langsung pada komputer, saat ini tidak dimungkinkan tanpa menggunakan debugger perangkat keras. Anda tidak dapat menggunakan debugger kernel untuk men-debug kode transport debug kernel. Mencoba melakukannya akan menyebabkan mesin reboot karena pecahnya tumpukan kernel (yang biasanya berakhir dengan kesalahan ganda dan reboot), atau kebuntuan, atau akan menyebabkan sistem transportasi diakses ulang, yang dalam banyak kasus akan menyebabkan sistem transportasi tidak berfungsi dengan benar.
Aturan penamaan modul untuk memperluas KDNET
Modul transportasi debug kernel Anda harus mengikuti salah satu dari dua konvensi penamaan untuk modul ekstensibilitas KDNET. Jika modul Anda mendukung perangkat keras berbasis PCI, maka modul tersebut harus diberi nama kd_YY_XXXX.dll di mana XXXX adalah ID vendor PCI perangkat keras Anda dalam format hex, dan YY adalah kelas PCI untuk perangkat keras Anda. Ada beberapa modul ekstensibilitas KDNET yang disertakan dalam Windows yang mendukung perangkat keras berbasis PCI. Misalnya, kd_02_8086.dll Intel, kd_02_14e4.dll Broadcom, dan kd_02_10ec.dll Realtek. Anda dapat mencari ID vendor PCI terdaftar di https://www.pcisig.com/membership/member-companies Semua modul ekstensibilitas KDNET berbasis PCI menggunakan VID vendor perangkat keras yang mereka dukung dalam hex sebagai 4 karakter terakhir dalam nama modul mereka. Kode kelas untuk sebagian besar modul dalam kotak adalah 02, karena mereka adalah perangkat kelas jaringan, dan karena itu memiliki kelas PCI 0x02 di ruang konfigurasi PCI mereka. Winload.exe membangun nama modul ekstensibilitas KDNET berbasis PCI dengan membaca kelas perangkat PCI dan PCI VID dari perangkat debug yang dipilih dari ruang konfigurasi PCI-nya, dan mencoba memuat modul dengan pengidentifikasi tersebut dalam nama. Jika perangkat Anda memiliki kode kelas PCI yang bukan kelas 0x02 jaringan, maka Anda harus menggunakan kode kelas PCI yang benar dalam heksadesimal untuk perangkat Anda, atas nama modul ekstensibilitas KDNET Anda. Jika tidak, modul Anda tidak akan dimuat dengan benar oleh winload. Di _02_ masing-masing nama tersebut adalah kode kelas PCI untuk perangkat kelas jaringan dalam format heksadesimal. Kode ini juga ditemukan dan dibaca dari ruang konfigurasi PCI perangkat debug.
Jika Anda memiliki perangkat yang memiliki entri tabel DBG2, dan bukan perangkat berbasis PCI, maka konvensi penamaan untuk modul Anda berbeda. Konvensi penamaan untuk perangkat debug tabel DBG2 adalah kd_XXXX_YYYY.dll, di mana XXXX adalah nilai hex dari PortType tabel DBG2, dan YYYY adalah nilai hex dari PortSubtype tabel DBG2 dari entri tabel DBG2. Kd_8003_5143.dll adalah DLL kotak masuk untuk mendukung PortType net (0x8003) dengan subjenis 0x5143. Dalam hal ini 5143 adalah Qualcomm PCI VID, karena ini mendukung KDNET pada pengontrol USB Qualcomm, dan untuk entri tabel Net DBG2, PortSubtype ditetapkan sebagai PCI VID untuk vendor perangkat keras. Perhatikan bahwa Anda dapat mendukung serial, USB, dan perangkat tabel DBG2 lainnya menggunakan konvensi penamaan ini. Berikut ini adalah nilai PortType yang saat ini didukung di hex: 8000 untuk perangkat serial, 8001 untuk 1394 perangkat, 8002 untuk perangkat USB, 8003 untuk perangkat NET. Perhatikan bahwa subjenis untuk perangkat serial dan USB harus didaftarkan pada Microsoft. Microsoft mempertahankan daftar subjenis serial dan USB yang dialokasikan. Silakan kirim email ke kdnet@microsoft.com untuk memesan subjenis serial atau USB, jika jenis yang didukung yang ada tidak akan berfungsi dengan perangkat keras Anda.
Impor Ekstensibilitas KDNET
Berikut ini adalah daftar rutinitas yang dapat Anda panggil dari modul ekstensibilitas KDNET. Perhatikan bahwa semua rutinitas ini diteruskan ke rutinitas KdInitializeLibrary, dan header kdnetextensibility.h akan memulihkan panggilan normal ke rutinitas ini untuk melalui tabel impor. Kode Anda harus memanggilnya melalui tabel impor, sehingga modul Anda tidak memiliki impor. Anda tidak boleh memanggil rutinitas lain yang diekspor oleh kernel, HAL, atau modul kernel lainnya. Anda hanya dapat memanggil rutinitas ini. Serangkaian rutinitas ini telah terbukti cukup untuk mengembangkan semua modul ekstensibilitas KDNET dalam paket, dan cukup memadai untuk skenario normal. Jika Anda memerlukan rutinitas tambahan yang diekspor oleh kernel, tetapi tidak ada dalam daftar ini, silakan kirim email untuk kdnet@microsoft.com menjelaskan skenario Anda, dan rutinitas tambahan mana yang Anda butuhkan dan mengapa. Perhatikan bahwa daftar ini hanya akan ditambahkan pada siklus rilis Windows utama, jika sama sekali terjadi. Perhatikan bahwa sebagian besar rutinitas ini sesuai langsung dengan API kernel Windows yang didukung oleh kernel atau HAL. Satu atau dua adalah rutinitas khusus KDNET saja.
Sangat penting bahwa Anda menyertakan kdnetextensibility.h dengan benar di header Anda sehingga pemetaan ulang rutinitas yang benar melalui tabel impor dapat terjadi. Jika ini tidak dilakukan, modul Anda akan memiliki impor, dan tidak akan didukung.
Membaca rutinitas memori tulis
Rutinitas berikut harus digunakan untuk membaca dan menulis ke memori perangkat yang dipetakan memori memori. Ini memiliki konvensi panggilan yang sama dan dipetakan ke rutinitas kernel yang sesuai: READ_REGISTER_UCHAR, READ_REGISTER_USHORT, READ_REGISTER_ULONG, WRITE_REGISTER_UCHAR, WRITE_REGISTER_USHORT, WRITE_REGISTER_ULONG, dan hanya pada platform 64-bit READ_REGISTER_ULONG64 dan WRITE_REGISTER_ULONG64. Semua akses memori perangkat harus dilakukan melalui rutinitas ini, karena memastikan bahwa pembacaan dan penulisan tidak diurutkan ulang oleh prosesor. Perhatikan bahwa dokumen di msdn.microsoft.com mendokumentasikan rutinitas Windows CE Compact 2013 yang sesuai dengan konvensi pemanggilan rutinitas ini. Sayangnya tampaknya rutinitas NT tidak didokumenkan, tetapi konvensi panggilannya sama.
Membaca rutinitas port IO
Rutinitas berikut harus digunakan untuk membaca dan menulis ke port IO perangkat. Ini memiliki konvensi panggilan yang sama dan dipetakan ke rutinitas kernel yang sesuai: READ_PORT_UCHAR, READ_PORT_USHORT, READ_PORT_ULONG, WRITE_PORT_UCHAR, WRITE_PORT_USHORT dan WRITE_PORT_ULONG. Semua akses port IO perangkat harus dilakukan melalui rutinitas ini. Perhatikan bahwa dokumen msdn.microsoft.com mencakup rutinitas Windows CE Compact 2013 yang sesuai dengan konvensi pemanggilan untuk rutinitas ini.
Rutinitas tambahan
Rutinitas tambahan berikut dapat dipanggil, dan harus dipanggil secara normal dengan parameter yang ditentukan. Perhatikan bahwa dengan melakukannya dan menyertakan header kdnetextensibility.h dengan benar, panggilan fungsi akan dipetakan ulang melalui tabel impor ekstensibilitas KDNET. Hasilnya, tidak ada impor eksplisit dalam modul Anda, sesuai dengan persyaratan untuk modul ekstensibilitas 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
);
Perhatikan bahwa fungsi PoSetHiberRange hanya boleh dipanggil dari rutinitas KdSetHibernateRange. Selain itu, sebagian besar modul ekstensibilitas KDNET tidak perlu memanggil KeBugCheckEx, KdMapPhysicalMemory64 dan KdUnmapVirtualAddress. Di sisi lain pada dasarnya semua modul ekstensibilitas KDNET perlu memanggil KdGetPhysicalAddress untuk mendapatkan alamat memori fisik yang diperlukan untuk memprogram mesin DMA perangkat, dan banyak yang perlu memanggil KeStallExecutionProcessor, KdGetPciDataByOffset dan KdSetPciDataByOffset. Dua rutinitas terakhir adalah untuk mengakses ruang konfigurasi PCI perangkat.
Ekspor Ekstensibilitas KDNET
Berikut ini adalah deskripsi singkat tentang setiap rutinitas ekstensibilitas KDNET. Anda harus menerapkan semua rutinitas yang diperlukan untuk modul ekstensiblitas KDNET berbasis paket, atau modul ekstensibilitas KDNET berbasis serial. Berikut ini adalah ekspor modul ekstensiblitas KDNET paket.
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;
}
Rutinitas ini dipanggil untuk melewati rutinitas impor dan ekspor antara KDNET dan modul ekstensibilitas KDNET ini. Rutinitas ini harus memvalidasi bahwa versi tabel impor dan ekspor diharapkan dan didukung, dan gagal jika tidak. Ini harus membuat salinan tabel impor dalam memori globalnya sendiri. Hal tersebut harus menuliskan rutinitas yang diekspor ke dalam struktur yang ditunjukkan oleh bidang Exports dari tabel impor. Ini juga harus mengatur bidang Panjang struktur Memori yang merupakan bagian dari penunjuk deskriptor perangkat debug yang diteruskan ke rutinitas ini, dengan jumlah byte memori yang diperlukan untuk mendukung perangkat keras.
Memvalidasi jumlah ekspor impor
Kode harus memeriksa bahwa Imports FunctionCount cocok dengan apa yang tersedia di OS, misalnya - (KdNetExtensibilityImports->FunctionCount != KDNET_EXT_IMPORTS) dan mengembalikan STATUS_INVALID_PARAMETER jika jumlahnya tidak cocok.
Memeriksa jumlah memastikan kompatibilitas antara versi KDNET OS Windows yang sedang berjalan (misalnya, boot manager/OS loader/hypervisor/Secure kernel/NT OS, yang semuanya ditautkan ke pustaka KDNET) dan versi WDK yang digunakan untuk membangun modul ekstensibilitas KDNET saat ini. WDK dan versi OS harus disinkronkan; jika tidak, pemeriksaan di atas akan gagal jika nilai penghitung impor/ekspor berubah. Misalnya jika antarmuka ekstensibilitas KDNET menambahkan fitur baru, jumlahnya tidak akan cocok lagi. Untuk memastikan bahwa mereka cocok, selalu gunakan rilis WDK yang cocok dengan OS yang menghosting versi KDNET.
Menyesuaikan memori yang diperlukan
Perhatikan bahwa perangkat akan diisi dengan perangkat keras yang dipilih untuk debugger. Rutinitas ini harus menyesuaikan jumlah memori yang diperlukan berdasarkan perangkat, jika diperlukan. Misalnya, modul ekstensibilitas yang mendukung perangkat keras 1Gig dan 10Gig, dapat meningkatkan ukuran memori yang mereka minta untuk perangkat 10Gig. Mereka dapat menentukan perangkat mana yang digunakan dengan memeriksa bidang DeviceID dari deskriptor perangkat debug.
KdInitializeLibrary adalah satu-satunya ekspor
Perhatikan bahwa rutinitas ini akan dipanggil baik oleh winload maupun oleh KDNET selama pemanggilan KdInitSystem. Perhatikan bahwa ini adalah SATU-SATUNYA rutinitas yang diekspor oleh modul ekstensibilitas KDNET. Ini adalah satu-satunya rutinitas yang ditempatkan dalam file .def. Modul perluasan KDNET memiliki tepat satu ekspor eksplisit - rutin ini - dan tidak ada impornya.
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.
--*/
Rutinitas ini dipanggil oleh sistem sebelum hibernasi sehingga dapat mendaftarkan kode yang digunakan oleh modul ekstensibilitas KDNET dengan sistem dengan benar. Ini memungkinkan sistem untuk mengelola memori tersebut dengan benar selama hibernasi dan melanjutkan dari hibernasi. (Memori akan disimpan terlambat, dan dimuat lebih awal, karena akan dipanggil sangat awal selama resume.)
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.
--*/
Rutinitas ini dipanggil untuk menginisialisasi perangkat keras. Ini dipanggil ketika sistem menginisialisasi, dan setiap kali sistem aktif kembali dari status daya rendah setelah memanggil KdShutdownController. Rutinitas ini HARUS memastikan bahwa perangkat keras telah sepenuhnya menyelesaikan inisialisasi dan siap untuk mengirim paket SEBELUM kembali. Rutinitas ini harus menunggu PHY muncul, dan agar tautan dibuat. Perhatikan bahwa jika tidak ada kabel yang terhubung, rutinitas ini tidak boleh terhenti tanpa batas waktu. Rutinitas ini mengatur kecepatan tautan dan dupleks dalam struktur data bersama KDNET yang dibagikan antara KDNET dan modul ekstensibilitas ini. Ini juga menulis alamat MAC yang digunakan oleh perangkat keras, ke lokasi yang ditunjukkan oleh TargetMacAddress dalam struktur data bersama 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.
--*/
Sangat penting bahwa rutinitas ini menanti hingga semua paket yang tertunda benar-benar dikirim melalui jaringan. Rutinitas ini perlu menunggu sampai semua paket pengiriman telah diproses melalui DMA dari memori utama dan keluar ke jaringan SEBELUM mematikan transmisi pada perangkat keras. Setelah semua paket pengiriman tertunda dikirim, rutinitas ini harus sepenuhnya mematikan perangkat keras. Rutinitas ini akan dipanggil ketika sistem dimatikan, dan juga ketika sistem memutuskan untuk mengelola transportasi debug ke status daya rendah. Ini dapat dipanggil ketika sistem masuk ke siaga, hibernasi, tidur, dan siaga yang terhubung, selain ketika sistem dimatikan.
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.
--*/
Rutinitas ini harus mengembalikan jumlah byte yang diperlukan untuk semua memori yang diperlukan untuk mendukung perangkat keras Anda. Ini termasuk struktur konteks Anda, dan semua buffer paket untuk pengiriman dan penerimaan, dan semua deskriptor paket perangkat keras serta struktur lainnya. Ukuran SEMUA memori yang Anda butuhkan perlu dilaporkan di sini. Termasuk memori tambahan yang diperlukan untuk batasan penyelarasan yang mungkin dimiliki perangkat keras Anda untuk paket, atau deskriptor paket atau struktur lainnya.
Perhatikan bahwa rutinitas ini harus dipanggil oleh rutinitas KdInitializeLibrary Anda saat mengatur bidang Panjang Memori di deskriptor perangkat 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.
--*/
Rutin ini mendapatkan paket berikutnya yang tersedia yang telah diterima, tetapi belum diproses. Ini mengembalikan penanganan untuk paket tersebut. Handel akan digunakan untuk mendapatkan alamat paket dengan memanggil KdGetPacketAddress, serta panjangnya dengan memanggil KdGetPacketLength. Paket dan handle harus tetap tersedia dan valid hingga paket dirilis dengan memanggil KdReleaseRxPacket. Rutinitas ini juga langsung mengembalikan alamat paket dan panjang ke pemanggil.
Jika saat ini tidak ada paket yang tersedia, rutinitas ini HARUS segera dikembalikan dengan STATUS_IO_TIMEOUT. Rutinitas ini TIDAK BOLEH menunggu paket diterima. Perhatikan bahwa dua bit teratas dari Handle telah dicadangkan. TRANSMIT_HANDLE dan TRANSMIT_ASYNC harus jelas.
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.
--*/
Rutinitas ini melepaskan sumber daya yang terkait dengan Handle paket kepada perangkat keras sehingga dapat digunakan untuk menerima paket lain. Setiap panggilan ke KdGetRxPacket yang berhasil akan diikuti oleh panggilan lain ke KdReleaseRxPacket dengan handel yang dikembalikan dari KdGetRxPacket. Perhatikan bahwa TIDAK dijamin bahwa KdReleaseRxPacket akan segera dipanggil setelah KdGetRxPacket berhasil. Ada kemungkinan bahwa panggilan KdGetRxPacket lain akan dilakukan terlebih dahulu. Namun, setiap panggilan KdGetRxPacket yang berhasil, akan merilis sumber dayanya dengan panggilan KdReleaseRxPacket.
Rutinitas ini harus memprogram perangkat keras dengan benar sehingga sumber daya yang dirilis dapat digunakan untuk menerima paket lain.
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.
--*/
Rutinitas ini mendapatkan sumber daya pengiriman berikutnya yang tersedia dan mengembalikan handel kepada mereka. Handel ini akan digunakan untuk memanggil KdGetPacketAddress, dan KdGetPacketLength. Alamat paket yang dikembalikan oleh KdGetPacketAddress akan digunakan untuk langsung menulis konten paket. Alamat paket harus menjadi awal paket, dan panjangnya harus berupa jumlah maksimum byte yang dapat ditulis ke dalam paket. Perhatikan bahwa jika tidak ada sumber daya perangkat keras yang tersedia, karena semuanya telah diperoleh, dan belum ditransmisikan, maka rutinitas ini harus segera mengembalikan STATUS_IO_TIMEOUT.
TRANSMIT_HANDLE harus diatur dalam pengendali yang dikembalikan. Perhatikan bahwa dua bit teratas Handle dicadangkan untuk bendera TRANSMIT_ASYNC dan 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.
--*/
Rutinitas ini mengirimkan paket yang terkait dengan handel yang diteruskan ke kawat. Perhatikan bahwa Handle mungkin memiliki bit tambahan yang diatur, yang menunjukkan apakah pengiriman tersebut merupakan transfer asinkron atau bukan. Jika bendera TRANSMIT_ASYNC diatur dalam handel, maka rutinitas ini harus memprogram perangkat keras untuk mengirim paket, dan kemudian harus segera kembali tanpa menunggu perangkat keras menyelesaikan pengiriman. Ini berarti bahwa setiap kesalahan yang terjadi selama pengiriman akan hilang. Itu tidak masalah, dan sengaja didesain begitu, karena paket dapat hilang dalam transmisi jaringan juga. Jika bendera TRANSMIT_ASYNC tidak diatur dalam Handel, maka rutinitas ini HARUS menunggu hingga paket dikirim pada kawat, dan harus mengembalikan kesalahan apa pun yang terjadi selama transmisi jika ada. Perhatikan bahwa ketika file cadangan dikirim ke host debugger, atau ketika paket jaringan Windows dikirim dari KDNIC melalui KDNET, maka TRANSMIT_ASYNC akan diatur. Ketika semua paket debugger lainnya dikirim, TRANSMIT_ASYNC akan tidak aktif.
Jika sekumpulan paket dikirim dengan TRANSMIT_ASYNC dikonfigurasi menjadi TRUE, diikuti oleh paket yang tidak memiliki TRANSMIT_ASYNC diatur, perangkat keras harus menunggu sampai paket tanpa bendera tersebut diatur benar-benar dikirim, bahkan jika ini berarti perangkat keras harus menunggu paket asinkron sebelumnya dikirim juga.
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.
--*/
Rutinitas ini mengembalikan penunjuk ke byte pertama dari paket yang dikaitkan dengan handle yang diberikan. Perhatikan bahwa Handle akan mengatur bit TRANSMIT_HANDLE untuk mengirimkan paket, dan TRANSMIT_HANDLE sedikit jelas untuk menerima paket. Penunjuk yang dikembalikan harus berupa alamat virtual Windows yang dapat dibaca atau ditulis oleh prosesor. Alamat ini harus berada dalam blok memori yang dicadangkan untuk modul ekstensi KDNET yang diteruskan dalam struktur memori deskriptor perangkat debug. (Perhatikan bahwa modul ekstensibilitas KDNET tidak boleh menggunakan lebih dari ukuran memori yang dimintanya di KdInitializeLibrary saat mengakses memori tersebut. Memori tambahan apa pun di akhir blok dicadangkan untuk digunakan oleh KDNET, dan tidak boleh disentuh oleh modul ekstensibilitas 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.
--*/
Rutinitas ini mengembalikan panjang dalam byte paket yang terkait dengan Handel yang diteruskan. Perhatikan bahwa Handle akan mengatur bit TRANSMIT_HANDLE untuk paket transmit, dan bit TRANSMIT_HANDLE akan diatur tidak aktif untuk paket penerima. Untuk mengirimkan paket, panjang ini harus berupa jumlah maksimum byte yang dapat ditulis ke paket. Untuk menerima paket, panjang ini harus menjadi jumlah byte aktual dalam paket yang diterima.
Debugging Modul Ekstensibilitas KDNET
Untuk melakukan debug modul ekstensibilitas KDNET, Anda perlu menjalankan perintah bcdedit berikut dari prompt perintah dengan hak admin pada komputer target.
Pertama, dan yang paling penting, Anda perlu menjalankan dua perintah berikut untuk memastikan bahwa Winload akan memungkinkan kegagalan boot berulang tanpa turun jalur kegagalan khusus yang menerobos ke debugger dan mencegah boot normal. Menjalankan perintah ini akan memungkinkan Anda untuk berulang kali me-reboot komputer dengan bit baru, dan men-debug bit baru tanpa masalah.
Bcdedit -set {current} BootStatusPolicy IgnoreAllFailures
Bcdedit -set {current} RecoveryEnabled No
Dengan asumsi Anda akan menggunakan debugging serial pada com1 pada komputer target untuk men-debug modul ekstensibilitas, lakukan hal berikut.
bcdedit -dbgsettings serial debugport:1 baudrate:115200
Ini mengatur transportasi debug default ke serial pada com1 pada 115200 baud. Pengaturan ini akan digunakan juga untuk debugging proses booting.
bcdedit -debug on
Ini memungkinkan debugging kernel.
bcdedit -bootdebug on
Ini memungkinkan penelusuran kesalahan boot pada winload.exe, yang akan Anda gunakan untuk melakukan debugging pada inisialisasi awal kernel termasuk modul ekstensi KDNET Anda.
bcdedit -set kerneldebugtype net
Ini memaksa tipe debug kernel menjadi net, tanpa mempedulikan pengaturan transport debug default. Ini akan menyebabkan winload.exe memuat kdnet.dll sebagai saluran debug kernel.
bcdedit -set kernelbusparams b.d.f
Di mana b adalah nomor bus, d adalah nomor perangkat dan f adalah nomor fungsi - semua dalam desimal - dari perangkat keras tempat Anda menulis modul ekstensiblitas KDNET. Angka-angka ini akan tergantung pada slot PCI tempat perangkat keras berada. Anda dapat menemukannya dengan menemukan string lokasi di halaman properti perangkat jaringan pada manajer perangkat Windows. Buka manajer perangkat Windows, klik dua kali pada perangkat jaringan, temukan perangkat Anda, klik dua kali padanya, dan di jendela yang terbuka harus ada Lokasi: bidang yang berisi bus, perangkat dan fungsi perangkat keras di bus PCI. Jika Anda memiliki pengemudi bus yang menyebabkan informasi tersebut terhalang, maka Anda harus menentukan lokasi dari sopir Anda, atau dengan cara lain.
Ini memaksa parameter bus kernel ke b.d.f – yang memaksa perangkat tertentu untuk dipilih sebagai perangkat debug kernel.
bcdedit -set kernelhostip N
Di mana N ditentukan oleh rumus berikut. Jika komputer debugger host Anda memiliki alamat IPv4 w.x.y.z, maka N = (w0x01000000) + (x0x00010000) + (y0x00000100) + (z0x00000001). N perlu ditentukan pada baris perintah dalam desimal, bukan hex. Secara efektif Anda mengambil setiap byte alamat IPv4 dan Anda menggabungkannya (dalam heksa) untuk membangun angka 32 bit dalam heksa, dan kemudian Anda mengonversinya menjadi desimal.
bcdedit -set kernelport N
Di mana N adalah 50000 atau beberapa port lain yang tidak akan diblokir di jaringan internal Anda.
Ini memaksa KDNET untuk menggunakan port N sebagai port debug jaringan.
bcdedit -set kernelkey 1.2.3.4
Ini memaksa kunci debug KDNET ke 1.2.3.4. 1.2.3.4 bukan kunci jaringan yang aman atau unik. Untuk menjaga keamanan komputer target, paket yang melakukan perjalanan antara host dan komputer target harus dienkripsi. Kami sangat menyarankan Agar Anda menggunakan kunci enkripsi yang dihasilkan secara otomatis. Untuk informasi selengkapnya, lihat Menyiapkan Penelusuran Kesalahan Kernel Jaringan KDNET Secara Otomatis.
bcdedit -set kerneldhcp on
Ini memaksa pengaturan dhcp kernel KDNET menjadi aktif.
Jalankan debugger Anda pada komputer host debugger dengan baris perintah berikut dengan asumsi Bahwa Anda menggunakan com1 sebagai port debug serial Anda pada komputer host:
windbg -d -k com:port=com1,baud=115200
Itu akan menjalankan debugger dan akan menyebabkannya pecah ketika debugger boot windbg pertama kali berkomunikasi dengan komputer host.
Kemudian mulai ulang komputer sasaran dengan menjalankan
shutdown -r -t 0
Ketika debugger pecah menjadi windbg, pastikan Anda mendapatkan simbol yang dimuat untuk winload. (mungkin perlu mengatur .sympath dan melakukan .reload). Kemudian jalankan x winload!*deb*tra*. Salah satu simbol yang tercantum akan menjadi sesuatu seperti BdDebugTransitions.
Kemudian jalankan ed winload!BdDebugTransitions 1, tetapi pastikan untuk menggunakan nama simbol yang benar.
Kemudian jalankan, bu winload!blbdstop untuk mengatur titik henti.
Kemudian tekan g untuk melanjutkan.
Anda harus menerobos di winload! BlBdStop.
Kemudian, jalankan perintah berikut.
bu nt!KdInitSystem
bu kdnet!KdInitialize
bu kdstub!KdInitializeLibrary
Perhatikan bahwa kemungkinan besar Anda akan menggunakan kdstub saat mengatur titik henti di modul ekstensibilitas KDNET Anda, jika itu tidak berfungsi, gunakan
bu kd_YY_XXXX!KdInitializeLibrary
Di mana YY adalah kelas PCI Anda, dan XXXX adalah PCI VID Anda. (yaitu: Gunakan nama modul ekstensibilitas KDNET Anda.)
Biasanya dalam debugger Anda harus menggunakan kdstub alih-alih menggunakan nama aktual modul ekstensibilitas Anda.
Kemudian jalankan bl untuk mencantumkan titik henti. Pastikan titik penghentian berada di tempat (semuanya harus memiliki e di sampingnya).
Kemudian tekan g. Anda harus mencapai breakpoint nt!KdInitSystem.
Tekan g lagi, dan Anda seharusnya memulai kdnet!KdInitialize
Tekan g lagi dan Anda akan mencapai titik henti pada modul Anda sendiri di KdInitializeLibrary.
Kemudian Anda dapat mengatur titik henti pada rutinitas InitializeController Anda, serta semua rutinitas Anda yang lain, dan menelusuri kode Anda.
Setelah Anda melangkah melalui KdInitializeLibrary, tekan g, dan jika Anda mengatur titik henti pada rutinitas InitializeController Anda, yang akan terpukul berikutnya.
Kemudian setelah selesai, pastikan Anda memiliki titik henti yang diatur pada rutinitas KdGetTxPacket, KdSendTxPacket, KdGetRxPacket, KdReleaseRxPacket Anda, dan tekan g lagi, dan rutinitas tersebut akan dijalankan sebagai bagian dari inisialisasi jaringan yang dilakukan oleh KDNET selama boot.
Anda mungkin perlu menambahkan kode sementara ke rutinitas KdInitializeLibrary atau KdInitializeController untuk memastikan bahwa semua rutinitas Anda dipanggil sehingga Anda dapat menelusuri semua kode Anda. (KdShutdownController misalnya tidak akan dipanggil selama startup ketika hal-hal bekerja secara normal, jadi Anda harus secara eksplisit memanggilnya dari kode sementara sehingga Anda dapat menelusurinya dan memastikannya benar.)
Setelah Anda menelusuri semua kode Anda dan yakin itu benar, maka restart target, tetapi JANGAN atur winload!BdDebugTransitions flag ke true (biarkan tetap bernilai nol).
Kemudian jalankan juga instans lain dari debugger kernel di komputer debugger host Anda.
Windbg -d -k net:port=50000,key=1.2.3.4
Biarkan komputer target boot, dan itu seharusnya terhubung ke instans lain dari debugger kernel melalui jaringan.
Kemudian jalankan perintah di debugger kernel dan pastikan itu berfungsi, lalu biarkan target melanjutkan booting, dan pastikan Anda nantinya dapat menghentikan sementara dan menjalankan perintah.
Catatan
Mengatur bendera transisi debug dalam winload, menjamin bahwa Windows TIDAK AKAN BOOT. Jika Anda mencoba memperbolehkan Windows menyelesaikan boot setelah mengatur bendera tersebut, Windows hanya akan mengalami crash, atau macet. Jika Anda ingin Windows berhasil boot, Anda tidak dapat mengatur bendera transisi debug tersebut. Mengatur penanda memungkinkan Anda untuk men-debug kode Anda dan memverifikasi bahwa itu benar dengan menelusurinya di debugger, tetapi pada akhirnya Anda perlu memastikan untuk tidak mengatur penanda tersebut agar Anda dapat memverifikasi bahwa penelusuran kesalahan berfungsi saat Anda melakukan booting secara normal. Ini berarti Bahwa Anda tidak dapat melangkah melalui kode Anda saat booting sistem secara normal, dan pada kenyataannya, ketika Windows berjalan normal, dengan debugging diaktifkan pada perangkat keras Anda, modul ekstensibilitas KDNET Anda tidak dapat di-debug. Setiap upaya untuk men-debugnya dengan debugger kernel, akan menyebabkan mesin mengalami crash. (Anda tidak dapat mengatur titik henti dalam kode yang berjalan di jalur debug kernel, karena menyebabkan rekursi tak terbatas, stack overflow, dan restart.)
Beberapa Fungsi Fisik - 2PF
Selain ekstensibilitas KDNET, KDNET mendukung penelusuran kesalahan kernel dengan menggunakan beberapa Fungsi Fisik (PF) pada NIC yang didukung melalui pemartisian ruang konfigurasi PCI. Vendor kartu jaringan didorong untuk mengaktifkan dukungan untuk fitur ini. Untuk informasi selengkapnya, lihat Debugger 2PF KDNET Miniport Network Driver Support.
Lihat juga
Mengatur debugging kernel jaringan KDNET secara otomatis