Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

495 lines
11 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. input.c
  5. Author:
  6. Ken Reneris Oct-2-1997
  7. Abstract:
  8. --*/
  9. #if defined (_IA64_)
  10. #include "bootia64.h"
  11. #endif
  12. #if defined (_X86_)
  13. #include "bldrx86.h"
  14. #endif
  15. #include "displayp.h"
  16. #include "stdio.h"
  17. #include "efi.h"
  18. #include "efip.h"
  19. #include "flop.h"
  20. #include "bootefi.h"
  21. //
  22. // Externals
  23. //
  24. extern BOOT_CONTEXT BootContext;
  25. extern EFI_HANDLE EfiImageHandle;
  26. extern EFI_SYSTEM_TABLE *EfiST;
  27. extern EFI_BOOT_SERVICES *EfiBS;
  28. extern EFI_RUNTIME_SERVICES *EfiRS;
  29. extern EFI_GUID EfiDevicePathProtocol;
  30. extern EFI_GUID EfiBlockIoProtocol;
  31. //
  32. // Globals
  33. //
  34. ULONGLONG InputTimeout = 0;
  35. //
  36. // Takes any pending input and converts it into a KEY value. Non-blocking, returning 0 if no input available.
  37. //
  38. ULONG
  39. BlGetKey()
  40. {
  41. ULONG Key = 0;
  42. UCHAR Ch;
  43. ULONG Count;
  44. if (ArcGetReadStatus(BlConsoleInDeviceId) == ESUCCESS) {
  45. ArcRead(BlConsoleInDeviceId, &Ch, sizeof(Ch), &Count);
  46. if (Ch == ASCI_CSI_IN) {
  47. if (ArcGetReadStatus(BlConsoleInDeviceId) == ESUCCESS) {
  48. ArcRead(BlConsoleInDeviceId, &Ch, sizeof(Ch), &Count);
  49. //
  50. // All the function keys start with ESC-O
  51. //
  52. switch (Ch) {
  53. case 'O':
  54. ArcRead(BlConsoleInDeviceId, &Ch, sizeof(Ch), &Count); // will not or block, as the buffer is already filled
  55. switch (Ch) {
  56. case 'P':
  57. Key = F1_KEY;
  58. break;
  59. case 'Q':
  60. Key = F2_KEY;
  61. break;
  62. case 'w':
  63. Key = F3_KEY;
  64. break;
  65. case 'x':
  66. Key = F4_KEY;
  67. break;
  68. case 't':
  69. Key = F5_KEY;
  70. break;
  71. case 'u':
  72. Key = F6_KEY;
  73. break;
  74. case 'r':
  75. Key = F8_KEY;
  76. break;
  77. case 'M':
  78. Key = F10_KEY;
  79. break;
  80. }
  81. break;
  82. case 'A':
  83. Key = UP_ARROW;
  84. break;
  85. case 'B':
  86. Key = DOWN_ARROW;
  87. break;
  88. case 'C':
  89. Key = RIGHT_KEY;
  90. break;
  91. case 'D':
  92. Key = LEFT_KEY;
  93. break;
  94. case 'H':
  95. Key = HOME_KEY;
  96. break;
  97. case 'K':
  98. Key = END_KEY;
  99. break;
  100. case '@':
  101. Key = INS_KEY;
  102. break;
  103. case 'P':
  104. Key = DEL_KEY;
  105. break;
  106. case TAB_KEY:
  107. Key = BACKTAB_KEY;
  108. break;
  109. }
  110. } else { // Single escape key, as no input is waiting.
  111. Key = ESCAPE_KEY;
  112. }
  113. } else if (Ch == 0x8) {
  114. Key = BKSP_KEY;
  115. } else {
  116. Key = (ULONG)Ch;
  117. }
  118. }
  119. return Key;
  120. }
  121. VOID
  122. BlInputString(
  123. IN ULONG Prompt,
  124. IN ULONG CursorX,
  125. IN ULONG PosY,
  126. IN PUCHAR String,
  127. IN ULONG MaxLength
  128. )
  129. {
  130. PTCHAR PromptString;
  131. ULONG TextX, TextY;
  132. ULONG Length, Index;
  133. _TUCHAR CursorChar[2];
  134. ULONG Key;
  135. _PTUCHAR p;
  136. ULONG i;
  137. ULONG Count;
  138. _PTUCHAR pString;
  139. #ifdef UNICODE
  140. WCHAR StringW[200];
  141. UNICODE_STRING uString;
  142. ANSI_STRING aString;
  143. pString = StringW;
  144. uString.Buffer = StringW;
  145. uString.MaximumLength = sizeof(StringW);
  146. RtlInitAnsiString(&aString, (PCHAR)String );
  147. RtlAnsiStringToUnicodeString( &uString, &aString, FALSE );
  148. #else
  149. pString = String;
  150. #endif
  151. PromptString = BlFindMessage(Prompt);
  152. Length = (ULONG)strlen((PCHAR)String);
  153. CursorChar[1] = TEXT('\0');
  154. //
  155. // Print prompt
  156. //
  157. BlEfiPositionCursor( PosY, CursorX );
  158. BlEfiEnableCursor( TRUE );
  159. ArcWrite(BlConsoleOutDeviceId, PromptString, (ULONG)_tcslen(PromptString)*sizeof(TCHAR), &Count);
  160. //
  161. // Indent cursor to right of prompt
  162. //
  163. CursorX += (ULONG)_tcslen(PromptString);
  164. TextX = CursorX;
  165. Key = 0;
  166. for (; ;) {
  167. TextY = TextX + Length;
  168. if (CursorX > TextY) {
  169. CursorX = TextY;
  170. }
  171. if (CursorX < TextX) {
  172. CursorX = TextX;
  173. }
  174. Index = CursorX - TextX;
  175. pString[Length] = 0;
  176. //
  177. // Display current string
  178. //
  179. BlEfiPositionCursor( TextY, TextX );
  180. ArcWrite(
  181. BlConsoleOutDeviceId,
  182. pString,
  183. (ULONG)_tcslen(pString)*sizeof(TCHAR),
  184. &Count);
  185. ArcWrite(BlConsoleOutDeviceId, TEXT(" "), sizeof(TEXT(" ")), &Count);
  186. if (Key == 0x0d) { // enter key?
  187. break ;
  188. }
  189. //
  190. // Display cursor
  191. //
  192. BlEfiPositionCursor( PosY, CursorX );
  193. BlEfiSetInverseMode( TRUE );
  194. CursorChar[0] = pString[Index] ? pString[Index] : TEXT(' ');
  195. ArcWrite(BlConsoleOutDeviceId, CursorChar, sizeof(_TUCHAR), &Count);
  196. BlEfiSetInverseMode( FALSE );
  197. BlEfiPositionCursor( PosY, CursorX );
  198. BlEfiEnableCursor(TRUE);
  199. //
  200. // Get key and process it
  201. //
  202. while ((Key = BlGetKey()) == 0) ;
  203. switch (Key) {
  204. case HOME_KEY:
  205. CursorX = TextX;
  206. break;
  207. case END_KEY:
  208. CursorX = TextY;
  209. break;
  210. case LEFT_KEY:
  211. CursorX -= 1;
  212. break;
  213. case RIGHT_KEY:
  214. CursorX += 1;
  215. break;
  216. case BKSP_KEY:
  217. if (!Index) {
  218. break;
  219. }
  220. CursorX -= 1;
  221. pString[Index-1] = CursorChar[0];
  222. // fallthough to DEL_KEY
  223. case DEL_KEY:
  224. if (Length) {
  225. p = pString+Index;
  226. i = Length-Index+1;
  227. while (i) {
  228. p[0] = p[1];
  229. p += 1;
  230. i -= 1;
  231. }
  232. Length -= 1;
  233. }
  234. break;
  235. case INS_KEY:
  236. if (Length < MaxLength) {
  237. p = pString+Length;
  238. i = Length-Index+1;
  239. while (i) {
  240. p[1] = p[0];
  241. p -= 1;
  242. i -= 1;
  243. }
  244. pString[Index] = TEXT(' ');
  245. Length += 1;
  246. }
  247. break;
  248. default:
  249. Key = Key & 0xff;
  250. if (Key >= ' ' && Key <= 'z') {
  251. if (CursorX == TextY && Length < MaxLength) {
  252. Length += 1;
  253. }
  254. pString[Index] = (_TUCHAR)Key;
  255. pString[MaxLength] = 0;
  256. CursorX += 1;
  257. }
  258. break;
  259. }
  260. }
  261. }
  262. ULONGLONG
  263. BlSetInputTimeout(
  264. ULONGLONG Timeout
  265. )
  266. /*++
  267. Routine Description:
  268. Sets the InputTimeout value. This is used
  269. when getting local input. When attempting
  270. to get local input, we will wait for up
  271. to InputTimeout for a local key to be
  272. pressed.
  273. Arguments:
  274. Timeout - Value to set the global InputTimeout to
  275. (in 100 nanoseconds)
  276. Return Value:
  277. The value stored in InputTimeout
  278. --*/
  279. {
  280. InputTimeout = Timeout;
  281. return InputTimeout;
  282. }
  283. ULONGLONG
  284. BlGetInputTimeout(
  285. VOID
  286. )
  287. /*++
  288. Routine Description:
  289. Gets the InputTimeout value. This is used
  290. when getting local input. When attempting
  291. to get local input, we will wait for up
  292. to InputTimeout for a local key to be
  293. pressed.
  294. Arguments:
  295. none.
  296. Return Value:
  297. The value stored in InputTimeout
  298. --*/
  299. {
  300. return InputTimeout;
  301. }
  302. EFI_STATUS
  303. BlWaitForInput(
  304. EFI_INPUT_KEY *Key,
  305. ULONGLONG Timeout
  306. )
  307. /*++
  308. Routine Description:
  309. creates an event consisting of a time interval
  310. and an efi event (local input). Once event
  311. is signaled, will check for input
  312. Assumes it is being called in PHYSICAL mode
  313. Arguments:
  314. Key - input key structure to return
  315. input in
  316. Timeout - Timer interval to wait.
  317. Return Value:
  318. EFI_TIMEOUT if timer interval met
  319. EFI_SUCCESS if passed in event is met.
  320. other error if EFI call failed.
  321. --*/
  322. {
  323. EFI_STATUS Status = EFI_SUCCESS;
  324. //
  325. // start by seeing if there is any pending input
  326. //
  327. Status = EfiST->ConIn->ReadKeyStroke(EfiST->ConIn,
  328. Key
  329. );
  330. if (Status == EFI_SUCCESS) {
  331. return Status;
  332. }
  333. //
  334. // create events to wait on
  335. //
  336. if (Timeout) {
  337. EFI_EVENT Event;
  338. EFI_EVENT TimerEvent;
  339. EFI_EVENT WaitList[2];
  340. UINTN Index;
  341. Event = EfiST->ConIn->WaitForKey;
  342. //
  343. // Create a timer event
  344. //
  345. Status = EfiBS->CreateEvent(EVT_TIMER, 0, NULL, NULL, &TimerEvent);
  346. if (Status == EFI_SUCCESS) {
  347. //
  348. // set the timer event
  349. //
  350. EfiBS->SetTimer(TimerEvent,
  351. TimerRelative,
  352. Timeout
  353. );
  354. //
  355. // Wait for the original event or timer
  356. //
  357. WaitList[0] = Event;
  358. WaitList[1] = TimerEvent;
  359. Status = EfiBS->WaitForEvent(2,
  360. WaitList,
  361. &Index
  362. );
  363. EfiBS->CloseEvent(TimerEvent);
  364. //
  365. // if the timer expired, change the return to timed out
  366. //
  367. if(Status == EFI_SUCCESS && Index == 1) {
  368. Status = EFI_TIMEOUT;
  369. }
  370. //
  371. // attempt to read local input
  372. //
  373. if (Status == EFI_SUCCESS) {
  374. Status = EfiST->ConIn->ReadKeyStroke(EfiST->ConIn,
  375. Key
  376. );
  377. }
  378. }
  379. }
  380. return Status;
  381. }