ktest.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971
  1. /*++
  2. Copyright (c) 2013 Minoca Corp.
  3. This file is licensed under the terms of the GNU General Public License
  4. version 3. Alternative licensing terms are available. Contact
  5. info@minocacorp.com for details. See the LICENSE file at the root of this
  6. project for complete licensing information.
  7. Module Name:
  8. ktest.c
  9. Abstract:
  10. This module implements the kernel test application.
  11. Author:
  12. Evan Green 5-Nov-2013
  13. Environment:
  14. User Mode
  15. --*/
  16. //
  17. // ------------------------------------------------------------------- Includes
  18. //
  19. #include <minoca/lib/minocaos.h>
  20. #include <assert.h>
  21. #include <errno.h>
  22. #include <fcntl.h>
  23. #include <getopt.h>
  24. #include <stdio.h>
  25. #include <stdlib.h>
  26. #include <string.h>
  27. #include <sys/ioctl.h>
  28. #include <time.h>
  29. #include <minoca/lib/mlibc.h>
  30. #include "ktestdrv.h"
  31. //
  32. // --------------------------------------------------------------------- Macros
  33. //
  34. #define DEBUG_PRINT(...) \
  35. if (KTestVerbosity >= TestVerbosityDebug) { \
  36. printf(__VA_ARGS__); \
  37. }
  38. #define PRINT(...) \
  39. if (KTestVerbosity >= TestVerbosityNormal) { \
  40. printf(__VA_ARGS__); \
  41. }
  42. #define PRINT_ERROR(...) fprintf(stderr, "\nktest: " __VA_ARGS__)
  43. //
  44. // ---------------------------------------------------------------- Definitions
  45. //
  46. #define KTEST_VERSION_MAJOR 1
  47. #define KTEST_VERSION_MINOR 0
  48. #define KTEST_USAGE \
  49. "Usage: ktest [options] \n" \
  50. "This utility hammers on various subsystems in the kernel. Options are:\n" \
  51. " -A <value>, -- Set the first test-specific parameter. -B sets the \n" \
  52. " second, -C the third, etc.\n" \
  53. " -i, --iterations <count> -- Set the number of operations to perform.\n" \
  54. " -p, --threads <count> -- Set the number of threads to spin up.\n" \
  55. " -t, --test -- Set the test to perform. Valid values are all, \n" \
  56. " pagedpoolstress, nonpagedpoolstress, workstress, threadstress, \n" \
  57. " descriptorstress, pagedblockstress and nonpagedblockstress.\n" \
  58. " --debug -- Print lots of information about what's happening.\n" \
  59. " --quiet -- Print only errors.\n" \
  60. " --no-cleanup -- Leave test files around for debugging.\n" \
  61. " --help -- Print this help text and exit.\n" \
  62. " --version -- Print the test version and exit.\n" \
  63. #define KTEST_OPTIONS_STRING "A:B:C:D:i:p:t:dqVh"
  64. #define KTEST_DRIVER_NAME "ktestdrv.drv"
  65. //
  66. // ------------------------------------------------------ Data Type Definitions
  67. //
  68. typedef enum _TEST_VERBOSITY {
  69. TestVerbosityQuiet,
  70. TestVerbosityNormal,
  71. TestVerbosityDebug
  72. } TEST_VERBOSITY, *PTEST_VERBOSITY;
  73. typedef struct _KTEST_PROGRESS {
  74. INT PreviousPercent;
  75. INT Handle;
  76. CHAR Character;
  77. KTEST_TYPE Test;
  78. } KTEST_PROGRESS, *PKTEST_PROGRESS;
  79. //
  80. // ----------------------------------------------- Internal Function Prototypes
  81. //
  82. KSTATUS
  83. KTestLoadDriver (
  84. VOID
  85. );
  86. KSTATUS
  87. KTestOpenDriver (
  88. PINT DriverHandle
  89. );
  90. VOID
  91. KTestCloseDriver (
  92. INT DriverHandle
  93. );
  94. INT
  95. KTestSendStartRequest (
  96. INT DriverHandle,
  97. KTEST_TYPE Test,
  98. PKTEST_START_TEST Request,
  99. PINT HandleCount
  100. );
  101. void
  102. KTestSignalHandler (
  103. int Signal
  104. );
  105. //
  106. // -------------------------------------------------------------------- Globals
  107. //
  108. //
  109. // Higher levels here print out more stuff.
  110. //
  111. TEST_VERBOSITY KTestVerbosity = TestVerbosityNormal;
  112. struct option KTestLongOptions[] = {
  113. {"iterations", required_argument, 0, 'i'},
  114. {"threads", required_argument, 0, 'p'},
  115. {"test", required_argument, 0, 't'},
  116. {"debug", no_argument, 0, 'd'},
  117. {"quiet", no_argument, 0, 'q'},
  118. {"help", no_argument, 0, 'h'},
  119. {"version", no_argument, 0, 'V'},
  120. {NULL, 0, 0, 0},
  121. };
  122. //
  123. // Store the handle array.
  124. //
  125. KTEST_PROGRESS KTestProgress[KTestCount];
  126. //
  127. // Store the friendly names of the tests.
  128. //
  129. PSTR KTestNames[KTestCount] = {
  130. "all",
  131. "pagedpoolstress",
  132. "nonpagedpoolstress",
  133. "workstress",
  134. "threadstress",
  135. "descriptorstress",
  136. "pagedblockstress",
  137. "nonpagedblockstress",
  138. };
  139. //
  140. // Store the UUID for querying test device information.
  141. //
  142. UUID KTestTestDeviceInformationUuid = TEST_DEVICE_INFORMATION_UUID;
  143. //
  144. // Stores a boolean indicating if a cancellation request was received.
  145. //
  146. BOOL KTestCancelAllTests = FALSE;
  147. //
  148. // ------------------------------------------------------------------ Functions
  149. //
  150. int
  151. main (
  152. int ArgumentCount,
  153. char **Arguments
  154. )
  155. /*++
  156. Routine Description:
  157. This routine implements the kernel test program.
  158. Arguments:
  159. ArgumentCount - Supplies the number of elements in the arguments array.
  160. Arguments - Supplies an array of strings. The array count is bounded by the
  161. previous parameter, and the strings are null-terminated.
  162. Return Value:
  163. 0 on success.
  164. Non-zero on failure.
  165. --*/
  166. {
  167. PSTR AfterScan;
  168. BOOL AllDone;
  169. BOOL AnyProgress;
  170. KTEST_CANCEL_TEST Cancel;
  171. INT DriverHandle;
  172. INT Failures;
  173. INT HandleCount;
  174. INT HandleIndex;
  175. INT Option;
  176. struct sigaction OriginalSigIntAction;
  177. ULONGLONG Percent;
  178. KTEST_POLL Poll;
  179. struct sigaction SigIntAction;
  180. KTEST_START_TEST Start;
  181. INT Status;
  182. KSTATUS StatusCode;
  183. KTEST_TYPE Test;
  184. ULONG TestIndex;
  185. PSTR TestName;
  186. DriverHandle = -1;
  187. Failures = 0;
  188. HandleCount = 0;
  189. Test = KTestAll;
  190. Status = 0;
  191. setvbuf(stdout, NULL, _IONBF, 0);
  192. setvbuf(stderr, NULL, _IONBF, 0);
  193. srand(time(NULL));
  194. memset(&Start, 0, sizeof(KTEST_START_TEST));
  195. for (HandleIndex = 0; HandleIndex < KTestCount; HandleIndex += 1) {
  196. KTestProgress[HandleIndex].Handle = -1;
  197. }
  198. //
  199. // Process the control arguments.
  200. //
  201. while (TRUE) {
  202. Option = getopt_long(ArgumentCount,
  203. Arguments,
  204. KTEST_OPTIONS_STRING,
  205. KTestLongOptions,
  206. NULL);
  207. if (Option == -1) {
  208. break;
  209. }
  210. if ((Option == '?') || (Option == ':')) {
  211. Status = 1;
  212. goto MainEnd;
  213. }
  214. switch (Option) {
  215. case 'A':
  216. case 'B':
  217. case 'C':
  218. case 'D':
  219. Start.Parameters.Parameters[Option - 'A'] =
  220. strtol(optarg, &AfterScan, 0);
  221. if (AfterScan == optarg) {
  222. PRINT_ERROR("Invalid parameter: %s.\n", optarg);
  223. Status = 1;
  224. goto MainEnd;
  225. }
  226. break;
  227. case 'i':
  228. Start.Parameters.Iterations = strtol(optarg, &AfterScan, 0);
  229. if ((Start.Parameters.Iterations < 0) || (AfterScan == optarg)) {
  230. PRINT_ERROR("Invalid iteration count %s.\n", optarg);
  231. Status = 1;
  232. goto MainEnd;
  233. }
  234. break;
  235. case 'p':
  236. Start.Parameters.Threads = strtol(optarg, &AfterScan, 0);
  237. if ((Start.Parameters.Threads <= 0) || (AfterScan == optarg)) {
  238. PRINT_ERROR("Invalid thread count %s.\n", optarg);
  239. Status = 1;
  240. goto MainEnd;
  241. }
  242. break;
  243. case 't':
  244. for (TestIndex = 0; TestIndex < KTestCount; TestIndex += 1) {
  245. if (strcasecmp(optarg, KTestNames[TestIndex]) == 0) {
  246. Test = TestIndex;
  247. break;
  248. }
  249. }
  250. if (TestIndex == KTestCount) {
  251. PRINT_ERROR("Invalid test: %s.\n", optarg);
  252. Status = 1;
  253. goto MainEnd;
  254. }
  255. break;
  256. case 'd':
  257. KTestVerbosity = TestVerbosityDebug;
  258. break;
  259. case 'q':
  260. KTestVerbosity = TestVerbosityQuiet;
  261. break;
  262. case 'V':
  263. printf("Minoca kernel test version %d.%d\n",
  264. KTEST_VERSION_MAJOR,
  265. KTEST_VERSION_MINOR);
  266. return 1;
  267. case 'h':
  268. printf(KTEST_USAGE);
  269. return 1;
  270. default:
  271. assert(FALSE);
  272. Status = 1;
  273. goto MainEnd;
  274. }
  275. }
  276. //
  277. // Fire up the driver.
  278. //
  279. StatusCode = KTestLoadDriver();
  280. if (!KSUCCESS(StatusCode)) {
  281. PRINT_ERROR("Error: Failed to load driver: %d.\n", StatusCode);
  282. Status = ClConvertKstatusToErrorNumber(StatusCode);
  283. goto MainEnd;
  284. }
  285. //
  286. // Give the device time to enumerate.
  287. //
  288. sleep(2);
  289. //
  290. // Open a connection to the driver.
  291. //
  292. StatusCode = KTestOpenDriver(&DriverHandle);
  293. if (!KSUCCESS(StatusCode)) {
  294. PRINT_ERROR("Error: Failed to open driver: %d.\n", StatusCode);
  295. Status = ClConvertKstatusToErrorNumber(StatusCode);
  296. goto MainEnd;
  297. }
  298. //
  299. // Run the tests.
  300. //
  301. HandleCount = 0;
  302. if ((Test == KTestAll) || (Test == KTestPagedPoolStress)) {
  303. Status = KTestSendStartRequest(DriverHandle,
  304. KTestPagedPoolStress,
  305. &Start,
  306. &HandleCount);
  307. if (Status != 0) {
  308. PRINT_ERROR("Failed to send start request.\n");
  309. Failures += 1;
  310. }
  311. }
  312. if ((Test == KTestAll) || (Test == KTestNonPagedPoolStress)) {
  313. Status = KTestSendStartRequest(DriverHandle,
  314. KTestNonPagedPoolStress,
  315. &Start,
  316. &HandleCount);
  317. if (Status != 0) {
  318. PRINT_ERROR("Failed to send start request.\n");
  319. Failures += 1;
  320. }
  321. }
  322. if ((Test == KTestAll) || (Test == KTestWorkStress)) {
  323. Status = KTestSendStartRequest(DriverHandle,
  324. KTestWorkStress,
  325. &Start,
  326. &HandleCount);
  327. if (Status != 0) {
  328. PRINT_ERROR("Failed to send start request.\n");
  329. Failures += 1;
  330. }
  331. }
  332. if ((Test == KTestAll) || (Test == KTestThreadStress)) {
  333. Status = KTestSendStartRequest(DriverHandle,
  334. KTestThreadStress,
  335. &Start,
  336. &HandleCount);
  337. if (Status != 0) {
  338. PRINT_ERROR("Failed to send start request.\n");
  339. Failures += 1;
  340. }
  341. }
  342. if ((Test == KTestAll) || (Test == KTestDescriptorStress)) {
  343. Status = KTestSendStartRequest(DriverHandle,
  344. KTestDescriptorStress,
  345. &Start,
  346. &HandleCount);
  347. if (Status != 0) {
  348. PRINT_ERROR("Failed to send start request.\n");
  349. Failures += 1;
  350. }
  351. }
  352. if ((Test == KTestAll) || (Test == KTestPagedBlockStress)) {
  353. Status = KTestSendStartRequest(DriverHandle,
  354. KTestPagedBlockStress,
  355. &Start,
  356. &HandleCount);
  357. if (Status != 0) {
  358. PRINT_ERROR("Failed to send start request.\n");
  359. Failures += 1;
  360. }
  361. }
  362. if ((Test == KTestAll) || (Test == KTestNonPagedBlockStress)) {
  363. Status = KTestSendStartRequest(DriverHandle,
  364. KTestNonPagedBlockStress,
  365. &Start,
  366. &HandleCount);
  367. if (Status != 0) {
  368. PRINT_ERROR("Failed to send start request.\n");
  369. Failures += 1;
  370. }
  371. }
  372. //
  373. // Poll the tests until they are all complete.
  374. //
  375. if (HandleCount == 0) {
  376. PRINT_ERROR("Error: No tests were started.\n");
  377. Failures += 1;
  378. goto MainEnd;
  379. }
  380. //
  381. // Handle cancellation signals.
  382. //
  383. memset(&SigIntAction, 0, sizeof(struct sigaction));
  384. SigIntAction.sa_handler = KTestSignalHandler;
  385. Status = sigaction(SIGINT, &SigIntAction, &OriginalSigIntAction);
  386. if (Status != 0) {
  387. PRINT_ERROR("Error: Failed to set SIGINT handler: %s.\n",
  388. strerror(errno));
  389. Failures += 1;
  390. KTestCancelAllTests = TRUE;
  391. goto MainEnd;
  392. }
  393. do {
  394. AllDone = TRUE;
  395. AnyProgress = FALSE;
  396. for (HandleIndex = 0; HandleIndex < HandleCount; HandleIndex += 1) {
  397. Poll.Handle = KTestProgress[HandleIndex].Handle;
  398. if (Poll.Handle < 0) {
  399. continue;
  400. }
  401. Status = ioctl(DriverHandle, KTestRequestPoll, &Poll);
  402. if (Status != 0) {
  403. PRINT_ERROR("Error: Failed to poll: %s.\n", strerror(errno));
  404. Failures += 1;
  405. continue;
  406. }
  407. if (!KSUCCESS(Poll.Status)) {
  408. PRINT_ERROR("Error: Poll returned %d.\n", Poll.Status);
  409. Failures += 1;
  410. continue;
  411. }
  412. if (Poll.TestFinished == FALSE) {
  413. AllDone = FALSE;
  414. }
  415. //
  416. // Spit out some progress characters if the needle has moved.
  417. //
  418. if (Poll.Total != 0) {
  419. Percent = (ULONGLONG)(Poll.Progress) * 100 / Poll.Total;
  420. while (Percent != KTestProgress[HandleIndex].PreviousPercent) {
  421. AnyProgress = TRUE;
  422. PRINT("%c", KTestProgress[HandleIndex].Character);
  423. KTestProgress[HandleIndex].PreviousPercent += 1;
  424. }
  425. }
  426. //
  427. // Print the results if finished.
  428. //
  429. if (Poll.TestFinished != FALSE) {
  430. TestName = KTestNames[KTestProgress[HandleIndex].Test];
  431. KTestProgress[HandleIndex].Handle = -1;
  432. PRINT("\n");
  433. if (Poll.Results.Failures != 0) {
  434. Failures += Poll.Results.Failures;
  435. PRINT_ERROR("Test %s finished with %d errors. Status %d.\n",
  436. TestName,
  437. Poll.Results.Failures,
  438. Poll.Results.Status);
  439. }
  440. switch (KTestProgress[HandleIndex].Test) {
  441. case KTestPagedPoolStress:
  442. case KTestNonPagedPoolStress:
  443. DEBUG_PRINT("%s: Max Allocation Count: %d\n"
  444. "Max Single Allocation Size: %d\n"
  445. "Max Allocated Memory: %d\n",
  446. TestName,
  447. Poll.Results.Results[0],
  448. Poll.Results.Results[1],
  449. Poll.Results.Results[2]);
  450. break;
  451. case KTestWorkStress:
  452. case KTestThreadStress:
  453. case KTestDescriptorStress:
  454. break;
  455. case KTestPagedBlockStress:
  456. case KTestNonPagedBlockStress:
  457. DEBUG_PRINT("%s: Max Allocation Count: %d\n"
  458. "Max Allocated Memory: %d\n",
  459. TestName,
  460. Poll.Results.Results[0],
  461. Poll.Results.Results[1]);
  462. break;
  463. default:
  464. assert(FALSE);
  465. break;
  466. }
  467. }
  468. }
  469. //
  470. // If no progress was printed, then sleep for a bit instead of
  471. // pounding the processor polling.
  472. //
  473. if ((AnyProgress == FALSE) && (AllDone == FALSE)) {
  474. sleep(1);
  475. }
  476. //
  477. // Kick out of the loop of all tests need to be canceled.
  478. //
  479. if (KTestCancelAllTests != FALSE) {
  480. break;
  481. }
  482. } while (AllDone == FALSE);
  483. Status = sigaction(SIGINT, &OriginalSigIntAction, NULL);
  484. if (Status != 0) {
  485. PRINT_ERROR("Error: Failed to restore SIGINT action: %s.\n",
  486. strerror(errno));
  487. Failures += 1;
  488. }
  489. MainEnd:
  490. PRINT("\n");
  491. if (KTestCancelAllTests != FALSE) {
  492. for (HandleIndex = 0; HandleIndex < HandleCount; HandleIndex += 1) {
  493. Cancel.Handle = KTestProgress[HandleIndex].Handle;
  494. Cancel.Status = STATUS_SUCCESS;
  495. Status = ioctl(DriverHandle, KTestRequestCancelTest, &Cancel);
  496. if (Status != 0) {
  497. PRINT_ERROR("Error: Failed to cacnel: %s.\n", strerror(errno));
  498. Failures += 1;
  499. continue;
  500. }
  501. if (!KSUCCESS(Cancel.Status)) {
  502. PRINT_ERROR("Error: Cancel returned %d.\n", Cancel.Status);
  503. Failures += 1;
  504. continue;
  505. }
  506. }
  507. }
  508. if (DriverHandle != -1) {
  509. Status = ioctl(DriverHandle, KTestRequestUnload, NULL);
  510. if (Status != 0) {
  511. PRINT_ERROR("Error: Failed to send unload ioctl: %s.\n",
  512. strerror(errno));
  513. Failures += 1;
  514. }
  515. KTestCloseDriver(DriverHandle);
  516. }
  517. if (Status != 0) {
  518. PRINT_ERROR("Error: %d.\n", Status);
  519. }
  520. if (Failures != 0) {
  521. PRINT_ERROR("\n *** %d failures in ktest ***\n", Failures);
  522. return Failures;
  523. }
  524. return 0;
  525. }
  526. //
  527. // --------------------------------------------------------- Internal Functions
  528. //
  529. KSTATUS
  530. KTestLoadDriver (
  531. VOID
  532. )
  533. /*++
  534. Routine Description:
  535. This routine loads the kernel test driver.
  536. Arguments:
  537. None.
  538. Return Value:
  539. Status code.
  540. --*/
  541. {
  542. PSTR CompletePath;
  543. UINTN CompletePathSize;
  544. PSTR CurrentDirectory;
  545. UINTN CurrentDirectorySize;
  546. UINTN DriverNameSize;
  547. KSTATUS Status;
  548. CompletePath = NULL;
  549. CurrentDirectory = getcwd(NULL, 0);
  550. if (CurrentDirectory == NULL) {
  551. Status = STATUS_UNSUCCESSFUL;
  552. goto LoadDriverEnd;
  553. }
  554. CurrentDirectorySize = strlen(CurrentDirectory);
  555. DriverNameSize = strlen(KTEST_DRIVER_NAME);
  556. CompletePathSize = CurrentDirectorySize + 1 + DriverNameSize + 1;
  557. CompletePath = malloc(CompletePathSize);
  558. if (CompletePath == NULL) {
  559. Status = STATUS_INSUFFICIENT_RESOURCES;
  560. goto LoadDriverEnd;
  561. }
  562. memcpy(CompletePath, CurrentDirectory, CurrentDirectorySize);
  563. CompletePath[CurrentDirectorySize] = '/';
  564. memcpy(CompletePath + CurrentDirectorySize + 1,
  565. KTEST_DRIVER_NAME,
  566. DriverNameSize);
  567. CompletePath[CompletePathSize - 1] = '\0';
  568. Status = OsLoadDriver(CompletePath, CompletePathSize);
  569. if (!KSUCCESS(Status)) {
  570. goto LoadDriverEnd;
  571. }
  572. LoadDriverEnd:
  573. if (CurrentDirectory != NULL) {
  574. free(CurrentDirectory);
  575. }
  576. if (CompletePath != NULL) {
  577. free(CompletePath);
  578. }
  579. return Status;
  580. }
  581. KSTATUS
  582. KTestOpenDriver (
  583. PINT DriverHandle
  584. )
  585. /*++
  586. Routine Description:
  587. This routine opens a handle to the kernel test driver.
  588. Arguments:
  589. DriverHandle - Supplies a pointer that receives the handle to the kernel
  590. test driver.
  591. Return Value:
  592. Status code.
  593. --*/
  594. {
  595. UINTN AllocationSize;
  596. UINTN DataSize;
  597. HANDLE Handle;
  598. ULONG ResultCount;
  599. UINTN ResultIndex;
  600. PDEVICE_INFORMATION_RESULT Results;
  601. KSTATUS Status;
  602. TEST_DEVICE_INFORMATION TestDeviceInformation;
  603. Handle = INVALID_HANDLE;
  604. ResultCount = 0;
  605. Results = NULL;
  606. //
  607. // Enumerate all the devices that support getting kernel test information.
  608. //
  609. Status = OsLocateDeviceInformation(&KTestTestDeviceInformationUuid,
  610. NULL,
  611. NULL,
  612. &ResultCount);
  613. if (Status != STATUS_BUFFER_TOO_SMALL) {
  614. goto OpenDriverEnd;
  615. }
  616. if (ResultCount == 0) {
  617. Status = STATUS_SUCCESS;
  618. goto OpenDriverEnd;
  619. }
  620. AllocationSize = sizeof(DEVICE_INFORMATION_RESULT) * ResultCount;
  621. Results = malloc(AllocationSize);
  622. if (Results == NULL) {
  623. Status = STATUS_INSUFFICIENT_RESOURCES;
  624. goto OpenDriverEnd;
  625. }
  626. memset(Results, 0, AllocationSize);
  627. Status = OsLocateDeviceInformation(&KTestTestDeviceInformationUuid,
  628. NULL,
  629. Results,
  630. &ResultCount);
  631. if (!KSUCCESS(Status)) {
  632. goto OpenDriverEnd;
  633. }
  634. if (ResultCount == 0) {
  635. Status = STATUS_SUCCESS;
  636. goto OpenDriverEnd;
  637. }
  638. //
  639. // Loop through the results trying to open the first kernel test device
  640. // that succeeds.
  641. //
  642. for (ResultIndex = 0; ResultIndex < ResultCount; ResultIndex += 1) {
  643. DataSize = sizeof(TEST_DEVICE_INFORMATION);
  644. Status = OsGetSetDeviceInformation(Results[ResultIndex].DeviceId,
  645. &KTestTestDeviceInformationUuid,
  646. &TestDeviceInformation,
  647. &DataSize,
  648. FALSE);
  649. if (KSUCCESS(Status) &&
  650. (TestDeviceInformation.Version >=
  651. TEST_DEVICE_INFORMATION_VERSION) &&
  652. (TestDeviceInformation.DeviceType == TestDeviceKernel)) {
  653. Status = OsOpenDevice(Results[ResultIndex].DeviceId,
  654. SYS_OPEN_FLAG_READ | SYS_OPEN_FLAG_WRITE,
  655. &Handle);
  656. if (KSUCCESS(Status)) {
  657. goto OpenDriverEnd;
  658. }
  659. }
  660. }
  661. Status = STATUS_NO_SUCH_DEVICE;
  662. OpenDriverEnd:
  663. if (Results != NULL) {
  664. free(Results);
  665. }
  666. *DriverHandle = (INT)(INTN)Handle;
  667. return Status;
  668. }
  669. VOID
  670. KTestCloseDriver (
  671. INT DriverHandle
  672. )
  673. /*++
  674. Routine Description:
  675. This routine closes the given driver handle.
  676. Arguments:
  677. DriverHandle - Supplies a handle to the driver to be closed.
  678. Return Value:
  679. None.
  680. --*/
  681. {
  682. OsClose((HANDLE)(UINTN)DriverHandle);
  683. return;
  684. }
  685. INT
  686. KTestSendStartRequest (
  687. INT DriverHandle,
  688. KTEST_TYPE Test,
  689. PKTEST_START_TEST Request,
  690. PINT HandleCount
  691. )
  692. /*++
  693. Routine Description:
  694. This routine sends a start request for the given test.
  695. Arguments:
  696. DriverHandle - Supplies the file descriptor to the open ktest device.
  697. Test - Supplies the test to start.
  698. Request - Supplies a pointer to the request parameters.
  699. HandleCount - Supplies a pointer that on input contains the valid handle
  700. count. This will be incremented on success.
  701. Return Value:
  702. 0 on success.
  703. Non-zero on failure.
  704. --*/
  705. {
  706. INT Status;
  707. Request->Parameters.TestType = Test;
  708. Request->Handle = -1;
  709. Status = ioctl(DriverHandle, KTestRequestStartTest, Request);
  710. if (Status != 0) {
  711. PRINT_ERROR("Failed to send start ioctl: %s.\n", strerror(errno));
  712. return 1;
  713. }
  714. assert(*HandleCount < KTestCount);
  715. if (!KSUCCESS(Request->Status)) {
  716. PRINT_ERROR("Start ioctl failed: %d\n", Request->Status);
  717. return 1;
  718. }
  719. KTestProgress[*HandleCount].Test = Test;
  720. KTestProgress[*HandleCount].Handle = Request->Handle;
  721. KTestProgress[*HandleCount].Character = 'A' + *HandleCount;
  722. KTestProgress[*HandleCount].PreviousPercent = 0;
  723. *HandleCount += 1;
  724. return 0;
  725. }
  726. void
  727. KTestSignalHandler (
  728. int Signal
  729. )
  730. /*++
  731. Routine Description:
  732. This routine handles the SIGINT signal while running the kernel test.
  733. Arguments:
  734. Signal - Supplies the signal number that fired.
  735. Return Value:
  736. None.
  737. --*/
  738. {
  739. assert(Signal == SIGINT);
  740. KTestCancelAllTests = TRUE;
  741. return;
  742. }