2 File abstractions of the console.
4 Manipulates EFI_FILE_PROTOCOL abstractions for stdin, stdout, stderr.
6 Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
7 This program and the accompanying materials are licensed and made available under
8 the terms and conditions of the BSD License that accompanies this distribution.
9 The full text of the license may be found at
10 http://opensource.org/licenses/bsd-license.php.
12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
17 #include <Library/BaseLib.h>
18 #include <Library/BaseMemoryLib.h>
19 #include <Library/MemoryAllocationLib.h>
20 #include <Library/UefiBootServicesTableLib.h>
22 #include <LibConfig.h>
23 #include <sys/EfiCdefs.h>
26 #include <sys/fcntl.h>
28 #include <Efi/Console.h>
30 static const CHAR16
* stdioNames
[NUM_SPECIAL
] = {
31 L
"stdin:", L
"stdout:", L
"stderr:"
33 static const int stdioFlags
[NUM_SPECIAL
] = {
39 static const int stdioMode
[NUM_SPECIAL
] = {
49 IN EFI_FILE_PROTOCOL
*This
54 Stream
= BASE_CR(This
, ConInstance
, Abstraction
);
55 // Quick check to see if Stream looks reasonable
56 if(Stream
->Cookie
!= 0x62416F49) { // Cookie == 'IoAb'
57 return RETURN_INVALID_PARAMETER
; // Looks like a bad This pointer
60 // Mark the Stream as closed.
63 return RETURN_SUCCESS
;
70 IN EFI_FILE_PROTOCOL
*This
73 return RETURN_UNSUPPORTED
;
80 IN EFI_FILE_PROTOCOL
*This
,
81 IN OUT UINTN
*BufferSize
,
85 EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*Proto
;
94 Stream
= BASE_CR(This
, ConInstance
, Abstraction
);
95 // Quick check to see if Stream looks reasonable
96 if(Stream
->Cookie
!= 0x62416F49) { // Cookie == 'IoAb'
97 return RETURN_INVALID_PARAMETER
; // Looks like a bad This pointer
99 if(Stream
->Dev
== NULL
) {
100 // Can't read from an unopened Stream
101 return RETURN_DEVICE_ERROR
;
103 if(Stream
!= &gMD
->StdIo
[0]) {
104 // Read only valid for stdin
105 return RETURN_UNSUPPORTED
;
107 // It looks like things are OK for trying to read
108 // We will accumulate *BufferSize characters or until we encounter
109 // an "activation" character. Currently any control character.
110 Proto
= (EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*)Stream
->Dev
;
112 NumChar
= (*BufferSize
- 1) / sizeof(CHAR16
);
115 Status
= gBS
->WaitForEvent( 1, &Proto
->WaitForKey
, &Edex
);
116 if(Status
!= EFI_SUCCESS
) {
119 Status
= Proto
->ReadKeyStroke(Proto
, &Key
);
120 if(Status
!= EFI_SUCCESS
) {
123 if(Key
.ScanCode
== SCAN_NULL
) {
124 *OutPtr
++ = Key
.UnicodeChar
;
127 if(Key
.UnicodeChar
< 0x0020) { // If a control character, or a scan code
130 } while(i
< NumChar
);
131 *BufferSize
= i
* sizeof(CHAR16
);
135 /* Write a NULL terminated WCS to the EFI console.
137 @param[in,out] BufferSize Number of bytes in Buffer. Set to zero if
138 the string couldn't be displayed.
139 @parem[in] Buffer The WCS string to be displayed
146 IN EFI_FILE_PROTOCOL
*This
,
147 IN OUT UINTN
*BufferSize
,
152 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*Proto
;
157 Stream
= BASE_CR(This
, ConInstance
, Abstraction
);
158 // Quick check to see if Stream looks reasonable
159 if(Stream
->Cookie
!= 0x62416F49) { // Cookie == 'IoAb'
160 return RETURN_INVALID_PARAMETER
; // Looks like a bad This pointer
162 if(Stream
->Dev
== NULL
) {
163 // Can't write to an unopened Stream
164 return RETURN_DEVICE_ERROR
;
166 if(Stream
== &gMD
->StdIo
[0]) {
167 // Write is not valid for stdin
168 return RETURN_UNSUPPORTED
;
170 // Everything is OK to do the write.
171 Proto
= (EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*)Stream
->Dev
;
172 MyBuf
= (CHAR16
*)Buffer
;
173 NumChar
= *BufferSize
;
175 // Send MyBuf to the console
176 Status
= Proto
->OutputString( Proto
, MyBuf
);
177 // Depending on status, update BufferSize and return
178 if(Status
!= EFI_SUCCESS
) {
179 *BufferSize
= 0; // We don't really know how many characters made it out
182 *BufferSize
= NumChar
;
183 Stream
->NumWritten
+= NumChar
;
192 IN EFI_FILE_PROTOCOL
*This
,
197 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*Proto
;
200 Stream
= BASE_CR(This
, ConInstance
, Abstraction
);
201 // Quick check to see if Stream looks reasonable
202 if(Stream
->Cookie
!= 0x62416F49) { // Cookie == 'IoAb'
203 return RETURN_INVALID_PARAMETER
; // Looks like a bad This pointer
205 if(Stream
== &gMD
->StdIo
[0]) {
207 *Position
= Stream
->NumRead
;
210 Proto
= (EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*)Stream
->Dev
;
211 CursorPos
.XYpos
.Column
= (UINT32
)Proto
->Mode
->CursorColumn
;
212 CursorPos
.XYpos
.Row
= (UINT32
)Proto
->Mode
->CursorRow
;
213 *Position
= CursorPos
.Offset
;
215 return RETURN_SUCCESS
;
222 IN EFI_FILE_PROTOCOL
*This
,
227 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*Proto
;
230 Stream
= BASE_CR(This
, ConInstance
, Abstraction
);
231 // Quick check to see if Stream looks reasonable
232 if(Stream
->Cookie
!= 0x62416F49) { // Cookie == 'IoAb'
233 return RETURN_INVALID_PARAMETER
; // Looks like a bad This pointer
235 if(Stream
->Dev
== NULL
) {
236 // Can't write to an unopened Stream
237 return RETURN_DEVICE_ERROR
;
239 if(Stream
== &gMD
->StdIo
[0]) {
240 // Seek is not valid for stdin
241 return RETURN_UNSUPPORTED
;
243 // Everything is OK to do the final verification and "seek".
244 Proto
= (EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*)Stream
->Dev
;
245 CursorPos
.Offset
= Position
;
247 return Proto
->SetCursorPosition(Proto
,
248 (INTN
)CursorPos
.XYpos
.Column
,
249 (INTN
)CursorPos
.XYpos
.Row
);
256 IN EFI_FILE_PROTOCOL
*This
,
257 IN EFI_GUID
*InformationType
,
258 IN OUT UINTN
*BufferSize
,
262 EFI_FILE_INFO
*InfoBuf
;
265 Stream
= BASE_CR(This
, ConInstance
, Abstraction
);
266 // Quick check to see if Stream looks reasonable
267 if((Stream
->Cookie
!= 0x62416F49) || // Cookie == 'IoAb'
270 return RETURN_INVALID_PARAMETER
;
272 if(*BufferSize
< sizeof(EFI_FILE_INFO
)) {
273 *BufferSize
= sizeof(EFI_FILE_INFO
);
274 return RETURN_BUFFER_TOO_SMALL
;
276 // All of our parameters are correct, so fill in the information.
277 (void) ZeroMem(Buffer
, sizeof(EFI_FILE_INFO
));
278 InfoBuf
= (EFI_FILE_INFO
*)Buffer
;
279 InfoBuf
->Size
= sizeof(EFI_FILE_INFO
);
280 InfoBuf
->FileSize
= 1;
281 InfoBuf
->PhysicalSize
= 1;
282 *BufferSize
= sizeof(EFI_FILE_INFO
);
284 return RETURN_SUCCESS
;
291 IN EFI_FILE_PROTOCOL
*This
,
292 IN EFI_GUID
*InformationType
,
297 return RETURN_UNSUPPORTED
;
304 IN EFI_FILE_PROTOCOL
*This
307 return RETURN_SUCCESS
;
313 IN EFI_FILE_PROTOCOL
*This
,
314 OUT EFI_FILE_PROTOCOL
**NewHandle
,
316 IN UINT64 OpenMode
, // Ignored
317 IN UINT64 Attributes
// Ignored
321 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*Proto
;
326 if((NewHandle
== NULL
) ||
329 return RETURN_INVALID_PARAMETER
;
332 for(i
= 0; i
< NUM_SPECIAL
; ++i
) {
333 if(StrCmp( stdioNames
[i
], FileName
) == 0) {
337 if(i
>= NUM_SPECIAL
) {
338 return RETURN_NO_MAPPING
;
340 // Get pointer to instance.
341 Stream
= &gMD
->StdIo
[i
];
342 if(Stream
->Dev
== NULL
) {
343 // If this stream has been closed, then
344 // Initialize instance.
345 Stream
->Cookie
= 0x62416F49;
347 Stream
->NumWritten
= 0;
350 Stream
->Dev
= gST
->ConIn
;
353 Stream
->Dev
= gST
->ConOut
;
356 if(gST
->StdErr
== NULL
) {
357 Stream
->Dev
= gST
->ConOut
;
360 Stream
->Dev
= gST
->StdErr
;
364 return RETURN_VOLUME_CORRUPTED
; // This is a "should never happen" case.
366 Stream
->Abstraction
.Revision
= 0x00010000;
367 Stream
->Abstraction
.Open
= &ConOpen
;
368 Stream
->Abstraction
.Close
= &ConClose
;
369 Stream
->Abstraction
.Delete
= &ConDelete
;
370 Stream
->Abstraction
.Read
= &ConRead
;
371 Stream
->Abstraction
.Write
= &ConWrite
;
372 Stream
->Abstraction
.GetPosition
= &ConGetPosition
;
373 Stream
->Abstraction
.SetPosition
= &ConSetPosition
;
374 Stream
->Abstraction
.GetInfo
= &ConGetInfo
;
375 Stream
->Abstraction
.SetInfo
= &ConSetInfo
;
376 Stream
->Abstraction
.Flush
= &ConFlush
;
377 // Get additional information if this is an Output stream
380 Stream
->ConOutMode
= Proto
->Mode
->Mode
;
381 if( Proto
->QueryMode(Proto
, Stream
->ConOutMode
, &Columns
, &Rows
) != RETURN_SUCCESS
) {
382 Stream
->Dev
= NULL
; // Mark this stream as closed
383 return RETURN_INVALID_PARAMETER
;
385 Stream
->MaxConXY
.XYpos
.Column
= (UINT32
)Columns
;
386 Stream
->MaxConXY
.XYpos
.Row
= (UINT32
)Rows
;
389 // Save NewHandle and return.
390 *NewHandle
= &Stream
->Abstraction
;
392 return RETURN_SUCCESS
;