2 * GRUB -- GRand Unified Bootloader
3 * Copyright (C) 2006,2007,2008,2012 Free Software Foundation, Inc.
5 * GRUB is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
10 * GRUB is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
19 #include <grub/disk.h>
20 #include <grub/partition.h>
22 #include <grub/types.h>
23 #include <grub/misc.h>
25 #include <grub/term.h>
26 #include <grub/efi/api.h>
27 #include <grub/efi/efi.h>
28 #include <grub/efi/disk.h>
29 #include <grub/serial.h>
30 #include <grub/types.h>
31 #include <grub/i18n.h>
34 static grub_efi_guid_t serial_io_guid
= GRUB_EFI_SERIAL_IO_GUID
;
37 do_real_config (struct grub_serial_port
*port
)
39 grub_efi_status_t status
= GRUB_EFI_SUCCESS
;
40 const grub_efi_parity_type_t parities
[] = {
41 [GRUB_SERIAL_PARITY_NONE
] = GRUB_EFI_SERIAL_NO_PARITY
,
42 [GRUB_SERIAL_PARITY_ODD
] = GRUB_EFI_SERIAL_ODD_PARITY
,
43 [GRUB_SERIAL_PARITY_EVEN
] = GRUB_EFI_SERIAL_EVEN_PARITY
45 const grub_efi_stop_bits_t stop_bits
[] = {
46 [GRUB_SERIAL_STOP_BITS_1
] = GRUB_EFI_SERIAL_1_STOP_BIT
,
47 [GRUB_SERIAL_STOP_BITS_1_5
] = GRUB_EFI_SERIAL_1_5_STOP_BITS
,
48 [GRUB_SERIAL_STOP_BITS_2
] = GRUB_EFI_SERIAL_2_STOP_BITS
,
54 status
= efi_call_7 (port
->interface
->set_attributes
, port
->interface
,
56 0, 0, parities
[port
->config
.parity
],
57 port
->config
.word_len
,
58 stop_bits
[port
->config
.stop_bits
]);
59 if (status
!= GRUB_EFI_SUCCESS
)
62 status
= efi_call_2 (port
->interface
->set_control_bits
, port
->interface
,
63 port
->config
.rtscts
? 0x4002 : 0x2);
70 serial_hw_fetch (struct grub_serial_port
*port
)
72 grub_efi_uintn_t bufsize
= 1;
74 grub_efi_status_t status
= GRUB_EFI_SUCCESS
;
75 do_real_config (port
);
79 status
= efi_call_3 (port
->interface
->read
, port
->interface
, &bufsize
, &c
);
80 if (status
!= GRUB_EFI_SUCCESS
|| bufsize
== 0)
86 /* Put a character. */
88 serial_hw_put (struct grub_serial_port
*port
, const int c
)
90 grub_efi_uintn_t bufsize
= 1;
93 do_real_config (port
);
98 efi_call_3 (port
->interface
->write
, port
->interface
, &bufsize
, &c0
);
101 /* Initialize a serial device. PORT is the port number for a serial device.
102 SPEED is a DTE-DTE speed which must be one of these: 2400, 4800, 9600,
103 19200, 38400, 57600 and 115200. WORD_LEN is the word length to be used
104 for the device. Likewise, PARITY is the type of the parity and
105 STOP_BIT_LEN is the length of the stop bit. The possible values for
106 WORD_LEN, PARITY and STOP_BIT_LEN are defined in the header file as
109 serial_hw_configure (struct grub_serial_port
*port
,
110 struct grub_serial_config
*config
)
112 if (config
->parity
!= GRUB_SERIAL_PARITY_NONE
113 && config
->parity
!= GRUB_SERIAL_PARITY_ODD
114 && config
->parity
!= GRUB_SERIAL_PARITY_EVEN
)
115 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
116 N_("unsupported serial port parity"));
118 if (config
->stop_bits
!= GRUB_SERIAL_STOP_BITS_1
119 && config
->stop_bits
!= GRUB_SERIAL_STOP_BITS_1_5
120 && config
->stop_bits
!= GRUB_SERIAL_STOP_BITS_2
)
121 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
122 N_("unsupported serial port stop bits number"));
124 if (config
->word_len
< 5 || config
->word_len
> 8)
125 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
126 N_("unsupported serial port word length"));
128 port
->config
= *config
;
129 port
->configured
= 0;
131 /* FIXME: should check if the serial terminal was found. */
133 return GRUB_ERR_NONE
;
136 struct grub_serial_driver grub_efiserial_driver
=
138 .configure
= serial_hw_configure
,
139 .fetch
= serial_hw_fetch
,
144 grub_efiserial_init (void)
146 grub_efi_uintn_t num_handles
;
147 grub_efi_handle_t
*handles
;
148 grub_efi_handle_t
*handle
;
152 /* Find handles which support the disk io interface. */
153 handles
= grub_efi_locate_handle (GRUB_EFI_BY_PROTOCOL
, &serial_io_guid
,
158 /* Make a linked list of devices. */
159 for (handle
= handles
; num_handles
--; handle
++)
161 struct grub_serial_port
*port
;
162 struct grub_efi_serial_io_interface
*sio
;
164 sio
= grub_efi_open_protocol (*handle
, &serial_io_guid
,
165 GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL
);
167 /* This should not happen... Why? */
170 port
= grub_zalloc (sizeof (*port
));
174 port
->name
= grub_malloc (sizeof ("efiXXXXXXXXXXXXXXXXXXXX"));
177 grub_snprintf (port
->name
, sizeof ("efiXXXXXXXXXXXXXXXXXXXX"),
178 "efi%d", num_serial
++);
180 port
->driver
= &grub_efiserial_driver
;
181 port
->interface
= sio
;
182 err
= grub_serial_config_defaults (port
);
186 grub_serial_register (port
);