VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/FirmwareNew/EmbeddedPkg/GdbStub/SerialIo.c@ 101296

最後變更 在這個檔案從101296是 99404,由 vboxsync 提交於 21 月 前

Devices/EFI/FirmwareNew: Update to edk2-stable202302 and make it build, bugref:4643

  • 屬性 svn:eol-style 設為 native
檔案大小: 14.1 KB
 
1/** @file
2 Serial IO Abstraction for GDB stub. This allows an EFI consoles that shows up on the system
3 running GDB. One console for error information and another console for user input/output.
4
5 Basic packet format is $packet-data#checksum. So every command has 4 bytes of overhead: $,
6 #, 0, 0. The 0 and 0 are the ascii characters for the checksum.
7
8
9 Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
10
11 SPDX-License-Identifier: BSD-2-Clause-Patent
12
13**/
14
15#include <GdbStubInternal.h>
16
17//
18// Set TRUE if F Reply package signals a ctrl-c. We can not process the Ctrl-c
19// here we need to wait for the periodic callback to do this.
20//
21BOOLEAN gCtrlCBreakFlag = FALSE;
22
23//
24// If the periodic callback is called while we are processing an F packet we need
25// to let the callback know to not read from the serial stream as it could steal
26// characters from the F response packet
27//
28BOOLEAN gProcessingFPacket = FALSE;
29
30/**
31 Process a control-C break message.
32
33 Currently a place holder, remove the ASSERT when it gets implemented.
34
35 @param ErrNo Error information from the F reply packet or other source
36
37**/
38VOID
39GdbCtrlCBreakMessage (
40 IN UINTN ErrNo
41 )
42{
43 // See D.10.5 of gdb.pdf
44 // This should look like a break message. Should look like SIGINT
45
46 /* TODO: Make sure if we should do anything with ErrNo */
47 // Turn on the global Ctrl-C flag.
48 gCtrlCBreakFlag = TRUE;
49}
50
51/**
52 Parse the F reply packet and extract the return value and an ErrNo if it exists.
53
54 @param Packet Packet to parse like an F reply packet
55 @param ErrNo Buffer to hold Count bytes that were read
56
57 @retval -1 Error, not a valid F reply packet
58 @retval other Return the return code from the F reply packet
59
60**/
61INTN
62GdbParseFReplyPacket (
63 IN CHAR8 *Packet,
64 OUT UINTN *ErrNo
65 )
66{
67 INTN RetCode;
68
69 if (Packet[0] != 'F') {
70 // A valid response would be an F packet
71 return -1;
72 }
73
74 RetCode = AsciiStrHexToUintn (&Packet[1]);
75
76 // Find 1st comma
77 for ( ; *Packet != '\0' && *Packet != ','; Packet++) {
78 }
79
80 if (*Packet == '\0') {
81 *ErrNo = 0;
82 return RetCode;
83 }
84
85 *ErrNo = AsciiStrHexToUintn (++Packet);
86
87 // Find 2nd comma
88 for ( ; *Packet != '\0' && *Packet != ','; Packet++) {
89 }
90
91 if (*Packet == '\0') {
92 return RetCode;
93 }
94
95 if (*(++Packet) == 'C') {
96 GdbCtrlCBreakMessage (*ErrNo);
97 }
98
99 return RetCode;
100}
101
102/**
103 Read data from a FileDescriptor. On success number of bytes read is returned. Zero indicates
104 the end of a file. On error -1 is returned. If count is zero, GdbRead returns zero.
105
106 @param FileDescriptor Device to talk to.
107 @param Buffer Buffer to hold Count bytes that were read
108 @param Count Number of bytes to transfer.
109
110 @retval -1 Error
111 @retval {other} Number of bytes read.
112
113**/
114INTN
115GdbRead (
116 IN INTN FileDescriptor,
117 OUT VOID *Buffer,
118 IN UINTN Count
119 )
120{
121 CHAR8 Packet[128];
122 UINTN Size;
123 INTN RetCode;
124 UINTN ErrNo;
125 BOOLEAN ReceiveDone = FALSE;
126
127 // Send:
128 // "Fread,XX,YYYYYYYY,XX
129 //
130 // XX - FileDescriptor in ASCII
131 // YYYYYYYY - Buffer address in ASCII
132 // XX - Count in ASCII
133 // SS - check sum
134 //
135 Size = AsciiSPrint (Packet, sizeof (Packet), "Fread,%x,%x,%x", FileDescriptor, Buffer, Count);
136 // Packet array is too small if you got this ASSERT
137 ASSERT (Size < sizeof (Packet));
138
139 gProcessingFPacket = TRUE;
140 SendPacket (Packet);
141 Print ((CHAR16 *)L"Packet sent..\n");
142
143 do {
144 // Reply:
145 ReceivePacket (Packet, sizeof (Packet));
146 Print ((CHAR16 *)L"Command received..%c\n", Packet[0]);
147
148 // Process GDB commands
149 switch (Packet[0]) {
150 // Write memory command.
151 // M addr,length:XX...
152 case 'M':
153 WriteToMemory (Packet);
154 break;
155
156 // Fretcode, errno, Ctrl-C flag
157 // retcode - Count read
158 case 'F':
159 // Once target receives F reply packet that means the previous
160 // transactions are finished.
161 ReceiveDone = TRUE;
162 break;
163
164 // Send empty buffer
165 default:
166 SendNotSupported ();
167 break;
168 }
169 } while (ReceiveDone == FALSE);
170
171 RetCode = GdbParseFReplyPacket (Packet, &ErrNo);
172 Print ((CHAR16 *)L"RetCode: %x..ErrNo: %x..\n", RetCode, ErrNo);
173
174 if (ErrNo > 0) {
175 // Send error to the host if there is any.
176 SendError ((UINT8)ErrNo);
177 }
178
179 gProcessingFPacket = FALSE;
180
181 return RetCode;
182}
183
184/**
185 Write data to a FileDescriptor. On success number of bytes written is returned. Zero indicates
186 nothing was written. On error -1 is returned.
187
188 @param FileDescriptor Device to talk to.
189 @param Buffer Buffer to hold Count bytes that are to be written
190 @param Count Number of bytes to transfer.
191
192 @retval -1 Error
193 @retval {other} Number of bytes written.
194
195**/
196INTN
197GdbWrite (
198 IN INTN FileDescriptor,
199 OUT CONST VOID *Buffer,
200 IN UINTN Count
201 )
202{
203 CHAR8 Packet[128];
204 UINTN Size;
205 INTN RetCode;
206 UINTN ErrNo;
207 BOOLEAN ReceiveDone = FALSE;
208
209 // Send:
210 // #Fwrite,XX,YYYYYYYY,XX$SS
211 //
212 // XX - FileDescriptor in ASCII
213 // YYYYYYYY - Buffer address in ASCII
214 // XX - Count in ASCII
215 // SS - check sum
216 //
217 Size = AsciiSPrint (Packet, sizeof (Packet), "Fwrite,%x,%x,%x", FileDescriptor, Buffer, Count);
218 // Packet array is too small if you got this ASSERT
219 ASSERT (Size < sizeof (Packet));
220
221 SendPacket (Packet);
222 Print ((CHAR16 *)L"Packet sent..\n");
223
224 do {
225 // Reply:
226 ReceivePacket (Packet, sizeof (Packet));
227 Print ((CHAR16 *)L"Command received..%c\n", Packet[0]);
228
229 // Process GDB commands
230 switch (Packet[0]) {
231 // Read memory command.
232 // m addr,length.
233 case 'm':
234 ReadFromMemory (Packet);
235 break;
236
237 // Fretcode, errno, Ctrl-C flag
238 // retcode - Count read
239 case 'F':
240 // Once target receives F reply packet that means the previous
241 // transactions are finished.
242 ReceiveDone = TRUE;
243 break;
244
245 // Send empty buffer
246 default:
247 SendNotSupported ();
248 break;
249 }
250 } while (ReceiveDone == FALSE);
251
252 RetCode = GdbParseFReplyPacket (Packet, &ErrNo);
253 Print ((CHAR16 *)L"RetCode: %x..ErrNo: %x..\n", RetCode, ErrNo);
254
255 // Send error to the host if there is any.
256 if (ErrNo > 0) {
257 SendError ((UINT8)ErrNo);
258 }
259
260 return RetCode;
261}
262
263/**
264 Reset the serial device.
265
266 @param This Protocol instance pointer.
267
268 @retval EFI_SUCCESS The device was reset.
269 @retval EFI_DEVICE_ERROR The serial device could not be reset.
270
271**/
272EFI_STATUS
273EFIAPI
274GdbSerialReset (
275 IN EFI_SERIAL_IO_PROTOCOL *This
276 )
277{
278 return EFI_SUCCESS;
279}
280
281/**
282 Sets the baud rate, receive FIFO depth, transmit/receive time out, parity,
283 data buts, and stop bits on a serial device.
284
285 @param This Protocol instance pointer.
286 @param BaudRate The requested baud rate. A BaudRate value of 0 will use the
287 device's default interface speed.
288 @param ReceiveFifoDepth The requested depth of the FIFO on the receive side of the
289 serial interface. A ReceiveFifoDepth value of 0 will use
290 the device's default FIFO depth.
291 @param Timeout The requested time out for a single character in microseconds.
292 This timeout applies to both the transmit and receive side of the
293 interface. A Timeout value of 0 will use the device's default time
294 out value.
295 @param Parity The type of parity to use on this serial device. A Parity value of
296 DefaultParity will use the device's default parity value.
297 @param DataBits The number of data bits to use on the serial device. A DataBits
298 value of 0 will use the device's default data bit setting.
299 @param StopBits The number of stop bits to use on this serial device. A StopBits
300 value of DefaultStopBits will use the device's default number of
301 stop bits.
302
303 @retval EFI_SUCCESS The device was reset.
304 @retval EFI_DEVICE_ERROR The serial device could not be reset.
305
306**/
307EFI_STATUS
308EFIAPI
309GdbSerialSetAttributes (
310 IN EFI_SERIAL_IO_PROTOCOL *This,
311 IN UINT64 BaudRate,
312 IN UINT32 ReceiveFifoDepth,
313 IN UINT32 Timeout,
314 IN EFI_PARITY_TYPE Parity,
315 IN UINT8 DataBits,
316 IN EFI_STOP_BITS_TYPE StopBits
317 )
318{
319 return EFI_UNSUPPORTED;
320}
321
322/**
323 Set the control bits on a serial device
324
325 @param This Protocol instance pointer.
326 @param Control Set the bits of Control that are settable.
327
328 @retval EFI_SUCCESS The new control bits were set on the serial device.
329 @retval EFI_UNSUPPORTED The serial device does not support this operation.
330 @retval EFI_DEVICE_ERROR The serial device is not functioning correctly.
331
332**/
333EFI_STATUS
334EFIAPI
335GdbSerialSetControl (
336 IN EFI_SERIAL_IO_PROTOCOL *This,
337 IN UINT32 Control
338 )
339{
340 return EFI_UNSUPPORTED;
341}
342
343/**
344 Retrieves the status of the control bits on a serial device
345
346 @param This Protocol instance pointer.
347 @param Control A pointer to return the current Control signals from the serial device.
348
349 @retval EFI_SUCCESS The control bits were read from the serial device.
350 @retval EFI_DEVICE_ERROR The serial device is not functioning correctly.
351
352**/
353EFI_STATUS
354EFIAPI
355GdbSerialGetControl (
356 IN EFI_SERIAL_IO_PROTOCOL *This,
357 OUT UINT32 *Control
358 )
359{
360 return EFI_UNSUPPORTED;
361}
362
363/**
364 Writes data to a serial device.
365
366 @param This Protocol instance pointer.
367 @param BufferSize On input, the size of the Buffer. On output, the amount of
368 data actually written.
369 @param Buffer The buffer of data to write
370
371 @retval EFI_SUCCESS The data was written.
372 @retval EFI_DEVICE_ERROR The device reported an error.
373 @retval EFI_TIMEOUT The data write was stopped due to a timeout.
374
375**/
376EFI_STATUS
377EFIAPI
378GdbSerialWrite (
379 IN EFI_SERIAL_IO_PROTOCOL *This,
380 IN OUT UINTN *BufferSize,
381 IN VOID *Buffer
382 )
383{
384 GDB_SERIAL_DEV *SerialDev;
385 UINTN Return;
386
387 SerialDev = GDB_SERIAL_DEV_FROM_THIS (This);
388
389 Return = GdbWrite (SerialDev->OutFileDescriptor, Buffer, *BufferSize);
390 if (Return == (UINTN)-1) {
391 return EFI_DEVICE_ERROR;
392 }
393
394 if (Return != *BufferSize) {
395 *BufferSize = Return;
396 }
397
398 return EFI_SUCCESS;
399}
400
401/**
402 Writes data to a serial device.
403
404 @param This Protocol instance pointer.
405 @param BufferSize On input, the size of the Buffer. On output, the amount of
406 data returned in Buffer.
407 @param Buffer The buffer to return the data into.
408
409 @retval EFI_SUCCESS The data was read.
410 @retval EFI_DEVICE_ERROR The device reported an error.
411 @retval EFI_TIMEOUT The data write was stopped due to a timeout.
412
413**/
414EFI_STATUS
415EFIAPI
416GdbSerialRead (
417 IN EFI_SERIAL_IO_PROTOCOL *This,
418 IN OUT UINTN *BufferSize,
419 OUT VOID *Buffer
420 )
421{
422 GDB_SERIAL_DEV *SerialDev;
423 UINTN Return;
424
425 SerialDev = GDB_SERIAL_DEV_FROM_THIS (This);
426
427 Return = GdbRead (SerialDev->InFileDescriptor, Buffer, *BufferSize);
428 if (Return == (UINTN)-1) {
429 return EFI_DEVICE_ERROR;
430 }
431
432 if (Return != *BufferSize) {
433 *BufferSize = Return;
434 }
435
436 return EFI_SUCCESS;
437}
438
439//
440// Template used to initialize the GDB Serial IO protocols
441//
442GDB_SERIAL_DEV gdbSerialDevTemplate = {
443 GDB_SERIAL_DEV_SIGNATURE,
444 NULL,
445
446 { // SerialIo
447 SERIAL_IO_INTERFACE_REVISION,
448 GdbSerialReset,
449 GdbSerialSetAttributes,
450 GdbSerialSetControl,
451 GdbSerialGetControl,
452 GdbSerialWrite,
453 GdbSerialRead,
454 NULL
455 },
456 { // SerialMode
457 0, // ControlMask
458 0, // Timeout
459 0, // BaudRate
460 1, // RceiveFifoDepth
461 0, // DataBits
462 0, // Parity
463 0 // StopBits
464 },
465 {
466 {
467 {
468 HARDWARE_DEVICE_PATH,
469 HW_VENDOR_DP,
470 {
471 (UINT8)(sizeof (VENDOR_DEVICE_PATH) + sizeof (UINT32)),
472 (UINT8)((sizeof (VENDOR_DEVICE_PATH) + sizeof (UINT32)) >> 8)
473 },
474 },
475 EFI_SERIAL_IO_PROTOCOL_GUID
476 },
477 0,
478 {
479 END_DEVICE_PATH_TYPE,
480 END_ENTIRE_DEVICE_PATH_SUBTYPE,
481 {
482 (UINT8)(sizeof (EFI_DEVICE_PATH_PROTOCOL)),
483 (UINT8)(sizeof (EFI_DEVICE_PATH_PROTOCOL) >> 8)
484 }
485 },
486 },
487 GDB_STDIN,
488 GDB_STDOUT
489};
490
491/**
492 Make two serial consoles: 1) StdIn and StdOut via GDB. 2) StdErr via GDB.
493
494 These console show up on the remote system running GDB
495
496**/
497VOID
498GdbInitializeSerialConsole (
499 VOID
500 )
501{
502 EFI_STATUS Status;
503 GDB_SERIAL_DEV *StdOutSerialDev;
504 GDB_SERIAL_DEV *StdErrSerialDev;
505
506 // Use the template to make a copy of the Serial Console private data structure.
507 StdOutSerialDev = AllocateCopyPool (sizeof (GDB_SERIAL_DEV), &gdbSerialDevTemplate);
508 ASSERT (StdOutSerialDev != NULL);
509
510 // Fixup pointer after the copy
511 StdOutSerialDev->SerialIo.Mode = &StdOutSerialDev->SerialMode;
512
513 StdErrSerialDev = AllocateCopyPool (sizeof (GDB_SERIAL_DEV), &gdbSerialDevTemplate);
514 ASSERT (StdErrSerialDev != NULL);
515
516 // Fixup pointer and modify stuff that is different for StdError
517 StdErrSerialDev->SerialIo.Mode = &StdErrSerialDev->SerialMode;
518 StdErrSerialDev->DevicePath.Index = 1;
519 StdErrSerialDev->OutFileDescriptor = GDB_STDERR;
520
521 // Make a new handle with Serial IO protocol and its device path on it.
522 Status = gBS->InstallMultipleProtocolInterfaces (
523 &StdOutSerialDev->Handle,
524 &gEfiSerialIoProtocolGuid,
525 &StdOutSerialDev->SerialIo,
526 &gEfiDevicePathProtocolGuid,
527 &StdOutSerialDev->DevicePath,
528 NULL
529 );
530 ASSERT_EFI_ERROR (Status);
531
532 // Make a new handle with Serial IO protocol and its device path on it.
533 Status = gBS->InstallMultipleProtocolInterfaces (
534 &StdErrSerialDev->Handle,
535 &gEfiSerialIoProtocolGuid,
536 &StdErrSerialDev->SerialIo,
537 &gEfiDevicePathProtocolGuid,
538 &StdErrSerialDev->DevicePath,
539 NULL
540 );
541 ASSERT_EFI_ERROR (Status);
542}
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette