Codebase list grub2 / 1651968
* Cherry-picks to better handle TFTP timeouts on some arches: (LP: #1521612) - (7b386b7) efidisk: move device path helpers in core for efinet - (c52ae40) efinet: skip virtual IP devices when enumerating cards - (f348aee) efinet: enable hardware filters when opening interface Mathieu Trudel-Lapierre 8 years ago
11 changed file(s) with 574 addition(s) and 57 deletion(s). Raw diff Collapse all Expand all
00 # see git-dpm(1) from git-dpm package
1 99d5df36311e15d60a16f6cba6e3b4ca442b0472
2 99d5df36311e15d60a16f6cba6e3b4ca442b0472
1 1a8eacd20fdfc9e9d3adf15af0a24a5c025fa071
2 1a8eacd20fdfc9e9d3adf15af0a24a5c025fa071
33 e8f07821cce1bd0ab6d5622c2a42440f15f4fd71
44 e8f07821cce1bd0ab6d5622c2a42440f15f4fd71
55 grub2_2.02~beta2.orig.tar.xz
0 grub2 (2.02~beta2-33) UNRELEASED; urgency=medium
1
2 * Cherry-picks to better handle TFTP timeouts on some arches: (LP: #1521612)
3 - (7b386b7) efidisk: move device path helpers in core for efinet
4 - (c52ae40) efinet: skip virtual IP devices when enumerating cards
5 - (f348aee) efinet: enable hardware filters when opening interface
6
7 -- Mathieu Trudel-Lapierre <mathieu-tl@ubuntu.com> Thu, 03 Dec 2015 11:01:36 -0500
8
09 grub2 (2.02~beta2-32) unstable; urgency=medium
110
211 [ Mathieu Trudel-Lapierre ]
0 From c603d4c4d477f2592de30410685016e55d3b78c5 Mon Sep 17 00:00:00 2001
1 From: Andrei Borzenkov <arvidjaar@gmail.com>
2 Date: Thu, 7 May 2015 20:37:16 +0300
3 Subject: efidisk: move device path helpers in core for efinet
4
5 Patch-Name: efidisk-device-path-helpers-for-efinet.patch
6 Bug-Ubuntu: https://bugs.launchpad.net/ubuntu/+source/grub2/+bug/1521612
7 Last-Update: 2015-12-03
8 ---
9 grub-core/disk/efi/efidisk.c | 61 ++++++++------------------------------------
10 grub-core/kern/efi/efi.c | 41 +++++++++++++++++++++++++++++
11 include/grub/efi/efi.h | 4 +++
12 3 files changed, 55 insertions(+), 51 deletions(-)
13
14 diff --git a/grub-core/disk/efi/efidisk.c b/grub-core/disk/efi/efidisk.c
15 index 3b12c34..845c66f 100644
16 --- a/grub-core/disk/efi/efidisk.c
17 +++ b/grub-core/disk/efi/efidisk.c
18 @@ -43,47 +43,6 @@ static struct grub_efidisk_data *fd_devices;
19 static struct grub_efidisk_data *hd_devices;
20 static struct grub_efidisk_data *cd_devices;
21
22 -/* Duplicate a device path. */
23 -static grub_efi_device_path_t *
24 -duplicate_device_path (const grub_efi_device_path_t *dp)
25 -{
26 - grub_efi_device_path_t *p;
27 - grub_size_t total_size = 0;
28 -
29 - for (p = (grub_efi_device_path_t *) dp;
30 - ;
31 - p = GRUB_EFI_NEXT_DEVICE_PATH (p))
32 - {
33 - total_size += GRUB_EFI_DEVICE_PATH_LENGTH (p);
34 - if (GRUB_EFI_END_ENTIRE_DEVICE_PATH (p))
35 - break;
36 - }
37 -
38 - p = grub_malloc (total_size);
39 - if (! p)
40 - return 0;
41 -
42 - grub_memcpy (p, dp, total_size);
43 - return p;
44 -}
45 -
46 -/* Return the device path node right before the end node. */
47 -static grub_efi_device_path_t *
48 -find_last_device_path (const grub_efi_device_path_t *dp)
49 -{
50 - grub_efi_device_path_t *next, *p;
51 -
52 - if (GRUB_EFI_END_ENTIRE_DEVICE_PATH (dp))
53 - return 0;
54 -
55 - for (p = (grub_efi_device_path_t *) dp, next = GRUB_EFI_NEXT_DEVICE_PATH (p);
56 - ! GRUB_EFI_END_ENTIRE_DEVICE_PATH (next);
57 - p = next, next = GRUB_EFI_NEXT_DEVICE_PATH (next))
58 - ;
59 -
60 - return p;
61 -}
62 -
63 static struct grub_efidisk_data *
64 make_devices (void)
65 {
66 @@ -110,7 +69,7 @@ make_devices (void)
67 if (! dp)
68 continue;
69
70 - ldp = find_last_device_path (dp);
71 + ldp = grub_efi_find_last_device_path (dp);
72 if (! ldp)
73 /* This is empty. Why? */
74 continue;
75 @@ -150,11 +109,11 @@ find_parent_device (struct grub_efidisk_data *devices,
76 grub_efi_device_path_t *dp, *ldp;
77 struct grub_efidisk_data *parent;
78
79 - dp = duplicate_device_path (d->device_path);
80 + dp = grub_efi_duplicate_device_path (d->device_path);
81 if (! dp)
82 return 0;
83
84 - ldp = find_last_device_path (dp);
85 + ldp = grub_efi_find_last_device_path (dp);
86 ldp->type = GRUB_EFI_END_DEVICE_PATH_TYPE;
87 ldp->subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE;
88 ldp->length = sizeof (*ldp);
89 @@ -180,11 +139,11 @@ is_child (struct grub_efidisk_data *child,
90 grub_efi_device_path_t *dp, *ldp;
91 int ret;
92
93 - dp = duplicate_device_path (child->device_path);
94 + dp = grub_efi_duplicate_device_path (child->device_path);
95 if (! dp)
96 return 0;
97
98 - ldp = find_last_device_path (dp);
99 + ldp = grub_efi_find_last_device_path (dp);
100 ldp->type = GRUB_EFI_END_DEVICE_PATH_TYPE;
101 ldp->subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE;
102 ldp->length = sizeof (*ldp);
103 @@ -207,8 +166,8 @@ add_device (struct grub_efidisk_data **devices, struct grub_efidisk_data *d)
104 {
105 int ret;
106
107 - ret = grub_efi_compare_device_paths (find_last_device_path ((*p)->device_path),
108 - find_last_device_path (d->device_path));
109 + ret = grub_efi_compare_device_paths (grub_efi_find_last_device_path ((*p)->device_path),
110 + grub_efi_find_last_device_path (d->device_path));
111 if (ret == 0)
112 ret = grub_efi_compare_device_paths ((*p)->device_path,
113 d->device_path);
114 @@ -795,7 +754,7 @@ grub_efidisk_get_device_name (grub_efi_handle_t *handle)
115 if (! dp)
116 return 0;
117
118 - ldp = find_last_device_path (dp);
119 + ldp = grub_efi_find_last_device_path (dp);
120 if (! ldp)
121 return 0;
122
123 @@ -811,14 +770,14 @@ grub_efidisk_get_device_name (grub_efi_handle_t *handle)
124
125 /* It is necessary to duplicate the device path so that GRUB
126 can overwrite it. */
127 - dup_dp = duplicate_device_path (dp);
128 + dup_dp = grub_efi_duplicate_device_path (dp);
129 if (! dup_dp)
130 return 0;
131
132 while (1)
133 {
134 grub_efi_device_path_t *dup_ldp;
135 - dup_ldp = find_last_device_path (dup_dp);
136 + dup_ldp = grub_efi_find_last_device_path (dup_dp);
137 if (!(GRUB_EFI_DEVICE_PATH_TYPE (dup_ldp) == GRUB_EFI_MEDIA_DEVICE_PATH_TYPE
138 && (GRUB_EFI_DEVICE_PATH_SUBTYPE (dup_ldp) == GRUB_EFI_CDROM_DEVICE_PATH_SUBTYPE
139 || GRUB_EFI_DEVICE_PATH_SUBTYPE (dup_ldp) == GRUB_EFI_HARD_DRIVE_DEVICE_PATH_SUBTYPE)))
140 diff --git a/grub-core/kern/efi/efi.c b/grub-core/kern/efi/efi.c
141 index 3b6cf26..12102ef 100644
142 --- a/grub-core/kern/efi/efi.c
143 +++ b/grub-core/kern/efi/efi.c
144 @@ -422,6 +422,47 @@ grub_efi_get_device_path (grub_efi_handle_t handle)
145 GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
146 }
147
148 +/* Return the device path node right before the end node. */
149 +grub_efi_device_path_t *
150 +grub_efi_find_last_device_path (const grub_efi_device_path_t *dp)
151 +{
152 + grub_efi_device_path_t *next, *p;
153 +
154 + if (GRUB_EFI_END_ENTIRE_DEVICE_PATH (dp))
155 + return 0;
156 +
157 + for (p = (grub_efi_device_path_t *) dp, next = GRUB_EFI_NEXT_DEVICE_PATH (p);
158 + ! GRUB_EFI_END_ENTIRE_DEVICE_PATH (next);
159 + p = next, next = GRUB_EFI_NEXT_DEVICE_PATH (next))
160 + ;
161 +
162 + return p;
163 +}
164 +
165 +/* Duplicate a device path. */
166 +grub_efi_device_path_t *
167 +grub_efi_duplicate_device_path (const grub_efi_device_path_t *dp)
168 +{
169 + grub_efi_device_path_t *p;
170 + grub_size_t total_size = 0;
171 +
172 + for (p = (grub_efi_device_path_t *) dp;
173 + ;
174 + p = GRUB_EFI_NEXT_DEVICE_PATH (p))
175 + {
176 + total_size += GRUB_EFI_DEVICE_PATH_LENGTH (p);
177 + if (GRUB_EFI_END_ENTIRE_DEVICE_PATH (p))
178 + break;
179 + }
180 +
181 + p = grub_malloc (total_size);
182 + if (! p)
183 + return 0;
184 +
185 + grub_memcpy (p, dp, total_size);
186 + return p;
187 +}
188 +
189 static void
190 dump_vendor_path (const char *type, grub_efi_vendor_device_path_t *vendor)
191 {
192 diff --git a/include/grub/efi/efi.h b/include/grub/efi/efi.h
193 index a000c38..2245632 100644
194 --- a/include/grub/efi/efi.h
195 +++ b/include/grub/efi/efi.h
196 @@ -56,6 +56,10 @@ void EXPORT_FUNC(grub_efi_print_device_path) (grub_efi_device_path_t *dp);
197 char *EXPORT_FUNC(grub_efi_get_filename) (grub_efi_device_path_t *dp);
198 grub_efi_device_path_t *
199 EXPORT_FUNC(grub_efi_get_device_path) (grub_efi_handle_t handle);
200 +grub_efi_device_path_t *
201 +EXPORT_FUNC(grub_efi_find_last_device_path) (const grub_efi_device_path_t *dp);
202 +grub_efi_device_path_t *
203 +EXPORT_FUNC(grub_efi_duplicate_device_path) (const grub_efi_device_path_t *dp);
204 grub_err_t EXPORT_FUNC (grub_efi_finish_boot_services) (grub_efi_uintn_t *outbuf_size, void *outbuf,
205 grub_efi_uintn_t *map_key,
206 grub_efi_uintn_t *efi_desc_size,
0 From 1a8eacd20fdfc9e9d3adf15af0a24a5c025fa071 Mon Sep 17 00:00:00 2001
1 From: Andrei Borzenkov <arvidjaar@gmail.com>
2 Date: Tue, 16 Jun 2015 19:52:45 +0300
3 Subject: efinet: enable hardware filters when opening interface
4
5 Exclusive open on SNP will close all existing protocol instances which
6 may disable all receive filters on interface. Reinstall them after we
7 opened protocol exclusively.
8
9 Also follow UEFI specification recommendation and stop interfaces when
10 closing them:
11
12 Unexpected system errors, reboots and hangs can occur if an OS is loaded
13 and the network devices are not Shutdown() and Stopped().
14
15 Also by: Mark Salter <msalter@redhat.com>
16 Closes: 45204
17
18 Patch-Name: efinet-enable-hardware-filters-on-interface.patch
19 Bug: http://savannah.gnu.org/bugs/?45204
20 Bug-Ubuntu: https://bugs.launchpad.net/ubuntu/+source/grub2/+bug/1521612
21 Last-Update: 2015-12-03
22 ---
23 grub-core/net/drivers/efi/efinet.c | 25 +++++++++++++++++++++++++
24 include/grub/efi/api.h | 20 +++++++++++++++++---
25 2 files changed, 42 insertions(+), 3 deletions(-)
26
27 diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c
28 index 775abde..9e0c0ad 100644
29 --- a/grub-core/net/drivers/efi/efinet.c
30 +++ b/grub-core/net/drivers/efi/efinet.c
31 @@ -156,6 +156,29 @@ open_card (struct grub_net_card *dev)
32 return grub_error (GRUB_ERR_NET_NO_CARD, "%s: net initialize failed",
33 dev->name);
34
35 + /* Enable hardware receive filters if driver declares support for it.
36 + We need unicast and broadcast and additionaly all nodes and
37 + solicited multicast for IPv6. Solicited multicast is per-IPv6
38 + address and we currently do not have API to do it so simply
39 + try to enable receive of all multicast packets or evertyhing in
40 + the worst case (i386 PXE driver always enables promiscuous too).
41 +
42 + This does trust firmware to do what it claims to do.
43 + */
44 + if (net->mode->receive_filter_mask)
45 + {
46 + grub_uint32_t filters = GRUB_EFI_SIMPLE_NETWORK_RECEIVE_UNICAST |
47 + GRUB_EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST |
48 + GRUB_EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST;
49 +
50 + filters &= net->mode->receive_filter_mask;
51 + if (!(filters & GRUB_EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST))
52 + filters |= (net->mode->receive_filter_mask &
53 + GRUB_EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS);
54 +
55 + efi_call_6 (net->receive_filters, net, filters, 0, 0, 0, NULL);
56 + }
57 +
58 efi_call_4 (grub_efi_system_table->boot_services->close_protocol,
59 dev->efi_net, &net_io_guid,
60 grub_efi_image_handle, dev->efi_handle);
61 @@ -169,6 +192,8 @@ open_card (struct grub_net_card *dev)
62 static void
63 close_card (struct grub_net_card *dev)
64 {
65 + efi_call_1 (dev->efi_net->shutdown, dev->efi_net);
66 + efi_call_1 (dev->efi_net->stop, dev->efi_net);
67 efi_call_4 (grub_efi_system_table->boot_services->close_protocol,
68 dev->efi_net, &net_io_guid,
69 grub_efi_image_handle, dev->efi_handle);
70 diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h
71 index e5dd543..1a5e38c 100644
72 --- a/include/grub/efi/api.h
73 +++ b/include/grub/efi/api.h
74 @@ -1501,17 +1501,31 @@ enum
75 GRUB_EFI_NETWORK_INITIALIZED,
76 };
77
78 +enum
79 + {
80 + GRUB_EFI_SIMPLE_NETWORK_RECEIVE_UNICAST = 0x01,
81 + GRUB_EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST = 0x02,
82 + GRUB_EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST = 0x04,
83 + GRUB_EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS = 0x08,
84 + GRUB_EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST = 0x10,
85 + };
86 +
87 struct grub_efi_simple_network
88 {
89 grub_uint64_t revision;
90 grub_efi_status_t (*start) (struct grub_efi_simple_network *this);
91 - void (*stop) (void);
92 + grub_efi_status_t (*stop) (struct grub_efi_simple_network *this);
93 grub_efi_status_t (*initialize) (struct grub_efi_simple_network *this,
94 grub_efi_uintn_t extra_rx,
95 grub_efi_uintn_t extra_tx);
96 void (*reset) (void);
97 - void (*shutdown) (void);
98 - void (*receive_filters) (void);
99 + grub_efi_status_t (*shutdown) (struct grub_efi_simple_network *this);
100 + grub_efi_status_t (*receive_filters) (struct grub_efi_simple_network *this,
101 + grub_uint32_t enable,
102 + grub_uint32_t disable,
103 + grub_efi_boolean_t reset_mcast_filter,
104 + grub_efi_uintn_t mcast_filter_count,
105 + grub_efi_mac_address_t *mcast_filter);
106 void (*station_address) (void);
107 void (*statistics) (void);
108 void (*mcastiptomac) (void);
0 From a651971c4597cf8071594bf6a299af511b94ce3d Mon Sep 17 00:00:00 2001
1 From: Andrei Borzenkov <arvidjaar@gmail.com>
2 Date: Thu, 7 May 2015 20:37:17 +0300
3 Subject: efinet: skip virtual IPv4 and IPv6 devices when enumerating cards
4
5 EDK2 PXE driver creates two child devices - IPv4 and IPv6 - with
6 bound SNP instance. This means we get three cards for every physical
7 adapter when enumerating. Not only is this confusing, this may result
8 in grub ignoring packets that come in via the "wrong" card.
9
10 Example of device hierarchy is
11
12 Ctrl[91] PciRoot(0x0)/Pci(0x3,0x0)
13 Ctrl[95] PciRoot(0x0)/Pci(0x3,0x0)/MAC(525400123456,0x1)
14 Ctrl[B4] PciRoot(0x0)/Pci(0x3,0x0)/MAC(525400123456,0x1)/IPv4(0.0.0.0)
15 Ctrl[BC] PciRoot(0x0)/Pci(0x3,0x0)/MAC(525400123456,0x1)/IPv6(0000:0000:0000:0000:0000:0000:0000:0000)
16
17 Skip PXE created virtual devices when enumerating cards. Make sure to
18 find real card when applying initial autoconfiguration during PXE boot,
19 this information is associated with one of child devices.
20
21 Patch-Name: efinet-skip-virtual-devices-on-enumeration.patch
22 Bug-Ubuntu: https://bugs.launchpad.net/ubuntu/+source/grub2/+bug/1521612
23 Last-Update: 2015-12-03
24 ---
25 grub-core/net/drivers/efi/efinet.c | 51 +++++++++++++++++++++++++++++++++++++-
26 1 file changed, 50 insertions(+), 1 deletion(-)
27
28 diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c
29 index 658b3d1..775abde 100644
30 --- a/grub-core/net/drivers/efi/efinet.c
31 +++ b/grub-core/net/drivers/efi/efinet.c
32 @@ -208,6 +208,29 @@ grub_efinet_findcards (void)
33 {
34 grub_efi_simple_network_t *net;
35 struct grub_net_card *card;
36 + grub_efi_device_path_t *dp, *parent = NULL, *child = NULL;
37 +
38 + /* EDK2 UEFI PXE driver creates IPv4 and IPv6 messaging devices as
39 + children of main MAC messaging device. We only need one device with
40 + bound SNP per physical card, otherwise they compete with each other
41 + when polling for incoming packets.
42 + */
43 + dp = grub_efi_get_device_path (*handle);
44 + if (!dp)
45 + continue;
46 + for (; ! GRUB_EFI_END_ENTIRE_DEVICE_PATH (dp); dp = GRUB_EFI_NEXT_DEVICE_PATH (dp))
47 + {
48 + parent = child;
49 + child = dp;
50 + }
51 + if (child
52 + && GRUB_EFI_DEVICE_PATH_TYPE (child) == GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE
53 + && (GRUB_EFI_DEVICE_PATH_SUBTYPE (child) == GRUB_EFI_IPV4_DEVICE_PATH_SUBTYPE
54 + || GRUB_EFI_DEVICE_PATH_SUBTYPE (child) == GRUB_EFI_IPV6_DEVICE_PATH_SUBTYPE)
55 + && parent
56 + && GRUB_EFI_DEVICE_PATH_TYPE (parent) == GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE
57 + && GRUB_EFI_DEVICE_PATH_SUBTYPE (parent) == GRUB_EFI_MAC_ADDRESS_DEVICE_PATH_SUBTYPE)
58 + continue;
59
60 net = grub_efi_open_protocol (*handle, &net_io_guid,
61 GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
62 @@ -285,7 +308,33 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device,
63 if (! cdp)
64 continue;
65 if (grub_efi_compare_device_paths (dp, cdp) != 0)
66 - continue;
67 + {
68 + grub_efi_device_path_t *ldp, *dup_dp, *dup_ldp;
69 + int match;
70 +
71 + /* EDK2 UEFI PXE driver creates pseudo devices with type IPv4/IPv6
72 + as children of Ethernet card and binds PXE and Load File protocols
73 + to it. Loaded Image Device Path protocol will point to these pseudo
74 + devices. We skip them when enumerating cards, so here we need to
75 + find matching MAC device.
76 + */
77 + ldp = grub_efi_find_last_device_path (dp);
78 + if (GRUB_EFI_DEVICE_PATH_TYPE (ldp) != GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE
79 + || (GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) != GRUB_EFI_IPV4_DEVICE_PATH_SUBTYPE
80 + && GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) != GRUB_EFI_IPV6_DEVICE_PATH_SUBTYPE))
81 + continue;
82 + dup_dp = grub_efi_duplicate_device_path (dp);
83 + if (!dup_dp)
84 + continue;
85 + dup_ldp = grub_efi_find_last_device_path (dup_dp);
86 + dup_ldp->type = GRUB_EFI_END_DEVICE_PATH_TYPE;
87 + dup_ldp->subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE;
88 + dup_ldp->length = sizeof (*dup_ldp);
89 + match = grub_efi_compare_device_paths (dup_dp, cdp) == 0;
90 + grub_free (dup_dp);
91 + if (!match)
92 + continue;
93 + }
94 pxe = grub_efi_open_protocol (hnd, &pxe_io_guid,
95 GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
96 if (! pxe)
8282 xfs-crc-fix-symlink.patch
8383 ofdisk_add_sas_disks.patch
8484 efinet-open-Simple-Network-Protocol-exclusively.patch
85 efidisk-device-path-helpers-for-efinet.patch
86 efinet-skip-virtual-devices-on-enumeration.patch
87 efinet-enable-hardware-filters-on-interface.patch
4242 static struct grub_efidisk_data *hd_devices;
4343 static struct grub_efidisk_data *cd_devices;
4444
45 /* Duplicate a device path. */
46 static grub_efi_device_path_t *
47 duplicate_device_path (const grub_efi_device_path_t *dp)
48 {
49 grub_efi_device_path_t *p;
50 grub_size_t total_size = 0;
51
52 for (p = (grub_efi_device_path_t *) dp;
53 ;
54 p = GRUB_EFI_NEXT_DEVICE_PATH (p))
55 {
56 total_size += GRUB_EFI_DEVICE_PATH_LENGTH (p);
57 if (GRUB_EFI_END_ENTIRE_DEVICE_PATH (p))
58 break;
59 }
60
61 p = grub_malloc (total_size);
62 if (! p)
63 return 0;
64
65 grub_memcpy (p, dp, total_size);
66 return p;
67 }
68
69 /* Return the device path node right before the end node. */
70 static grub_efi_device_path_t *
71 find_last_device_path (const grub_efi_device_path_t *dp)
72 {
73 grub_efi_device_path_t *next, *p;
74
75 if (GRUB_EFI_END_ENTIRE_DEVICE_PATH (dp))
76 return 0;
77
78 for (p = (grub_efi_device_path_t *) dp, next = GRUB_EFI_NEXT_DEVICE_PATH (p);
79 ! GRUB_EFI_END_ENTIRE_DEVICE_PATH (next);
80 p = next, next = GRUB_EFI_NEXT_DEVICE_PATH (next))
81 ;
82
83 return p;
84 }
85
8645 static struct grub_efidisk_data *
8746 make_devices (void)
8847 {
10968 if (! dp)
11069 continue;
11170
112 ldp = find_last_device_path (dp);
71 ldp = grub_efi_find_last_device_path (dp);
11372 if (! ldp)
11473 /* This is empty. Why? */
11574 continue;
149108 grub_efi_device_path_t *dp, *ldp;
150109 struct grub_efidisk_data *parent;
151110
152 dp = duplicate_device_path (d->device_path);
111 dp = grub_efi_duplicate_device_path (d->device_path);
153112 if (! dp)
154113 return 0;
155114
156 ldp = find_last_device_path (dp);
115 ldp = grub_efi_find_last_device_path (dp);
157116 ldp->type = GRUB_EFI_END_DEVICE_PATH_TYPE;
158117 ldp->subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE;
159118 ldp->length = sizeof (*ldp);
179138 grub_efi_device_path_t *dp, *ldp;
180139 int ret;
181140
182 dp = duplicate_device_path (child->device_path);
141 dp = grub_efi_duplicate_device_path (child->device_path);
183142 if (! dp)
184143 return 0;
185144
186 ldp = find_last_device_path (dp);
145 ldp = grub_efi_find_last_device_path (dp);
187146 ldp->type = GRUB_EFI_END_DEVICE_PATH_TYPE;
188147 ldp->subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE;
189148 ldp->length = sizeof (*ldp);
206165 {
207166 int ret;
208167
209 ret = grub_efi_compare_device_paths (find_last_device_path ((*p)->device_path),
210 find_last_device_path (d->device_path));
168 ret = grub_efi_compare_device_paths (grub_efi_find_last_device_path ((*p)->device_path),
169 grub_efi_find_last_device_path (d->device_path));
211170 if (ret == 0)
212171 ret = grub_efi_compare_device_paths ((*p)->device_path,
213172 d->device_path);
794753 if (! dp)
795754 return 0;
796755
797 ldp = find_last_device_path (dp);
756 ldp = grub_efi_find_last_device_path (dp);
798757 if (! ldp)
799758 return 0;
800759
810769
811770 /* It is necessary to duplicate the device path so that GRUB
812771 can overwrite it. */
813 dup_dp = duplicate_device_path (dp);
772 dup_dp = grub_efi_duplicate_device_path (dp);
814773 if (! dup_dp)
815774 return 0;
816775
817776 while (1)
818777 {
819778 grub_efi_device_path_t *dup_ldp;
820 dup_ldp = find_last_device_path (dup_dp);
779 dup_ldp = grub_efi_find_last_device_path (dup_dp);
821780 if (!(GRUB_EFI_DEVICE_PATH_TYPE (dup_ldp) == GRUB_EFI_MEDIA_DEVICE_PATH_TYPE
822781 && (GRUB_EFI_DEVICE_PATH_SUBTYPE (dup_ldp) == GRUB_EFI_CDROM_DEVICE_PATH_SUBTYPE
823782 || GRUB_EFI_DEVICE_PATH_SUBTYPE (dup_ldp) == GRUB_EFI_HARD_DRIVE_DEVICE_PATH_SUBTYPE)))
419419 {
420420 return grub_efi_open_protocol (handle, &device_path_guid,
421421 GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
422 }
423
424 /* Return the device path node right before the end node. */
425 grub_efi_device_path_t *
426 grub_efi_find_last_device_path (const grub_efi_device_path_t *dp)
427 {
428 grub_efi_device_path_t *next, *p;
429
430 if (GRUB_EFI_END_ENTIRE_DEVICE_PATH (dp))
431 return 0;
432
433 for (p = (grub_efi_device_path_t *) dp, next = GRUB_EFI_NEXT_DEVICE_PATH (p);
434 ! GRUB_EFI_END_ENTIRE_DEVICE_PATH (next);
435 p = next, next = GRUB_EFI_NEXT_DEVICE_PATH (next))
436 ;
437
438 return p;
439 }
440
441 /* Duplicate a device path. */
442 grub_efi_device_path_t *
443 grub_efi_duplicate_device_path (const grub_efi_device_path_t *dp)
444 {
445 grub_efi_device_path_t *p;
446 grub_size_t total_size = 0;
447
448 for (p = (grub_efi_device_path_t *) dp;
449 ;
450 p = GRUB_EFI_NEXT_DEVICE_PATH (p))
451 {
452 total_size += GRUB_EFI_DEVICE_PATH_LENGTH (p);
453 if (GRUB_EFI_END_ENTIRE_DEVICE_PATH (p))
454 break;
455 }
456
457 p = grub_malloc (total_size);
458 if (! p)
459 return 0;
460
461 grub_memcpy (p, dp, total_size);
462 return p;
422463 }
423464
424465 static void
155155 return grub_error (GRUB_ERR_NET_NO_CARD, "%s: net initialize failed",
156156 dev->name);
157157
158 /* Enable hardware receive filters if driver declares support for it.
159 We need unicast and broadcast and additionaly all nodes and
160 solicited multicast for IPv6. Solicited multicast is per-IPv6
161 address and we currently do not have API to do it so simply
162 try to enable receive of all multicast packets or evertyhing in
163 the worst case (i386 PXE driver always enables promiscuous too).
164
165 This does trust firmware to do what it claims to do.
166 */
167 if (net->mode->receive_filter_mask)
168 {
169 grub_uint32_t filters = GRUB_EFI_SIMPLE_NETWORK_RECEIVE_UNICAST |
170 GRUB_EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST |
171 GRUB_EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST;
172
173 filters &= net->mode->receive_filter_mask;
174 if (!(filters & GRUB_EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST))
175 filters |= (net->mode->receive_filter_mask &
176 GRUB_EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS);
177
178 efi_call_6 (net->receive_filters, net, filters, 0, 0, 0, NULL);
179 }
180
158181 efi_call_4 (grub_efi_system_table->boot_services->close_protocol,
159182 dev->efi_net, &net_io_guid,
160183 grub_efi_image_handle, dev->efi_handle);
168191 static void
169192 close_card (struct grub_net_card *dev)
170193 {
194 efi_call_1 (dev->efi_net->shutdown, dev->efi_net);
195 efi_call_1 (dev->efi_net->stop, dev->efi_net);
171196 efi_call_4 (grub_efi_system_table->boot_services->close_protocol,
172197 dev->efi_net, &net_io_guid,
173198 grub_efi_image_handle, dev->efi_handle);
207232 {
208233 grub_efi_simple_network_t *net;
209234 struct grub_net_card *card;
235 grub_efi_device_path_t *dp, *parent = NULL, *child = NULL;
236
237 /* EDK2 UEFI PXE driver creates IPv4 and IPv6 messaging devices as
238 children of main MAC messaging device. We only need one device with
239 bound SNP per physical card, otherwise they compete with each other
240 when polling for incoming packets.
241 */
242 dp = grub_efi_get_device_path (*handle);
243 if (!dp)
244 continue;
245 for (; ! GRUB_EFI_END_ENTIRE_DEVICE_PATH (dp); dp = GRUB_EFI_NEXT_DEVICE_PATH (dp))
246 {
247 parent = child;
248 child = dp;
249 }
250 if (child
251 && GRUB_EFI_DEVICE_PATH_TYPE (child) == GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE
252 && (GRUB_EFI_DEVICE_PATH_SUBTYPE (child) == GRUB_EFI_IPV4_DEVICE_PATH_SUBTYPE
253 || GRUB_EFI_DEVICE_PATH_SUBTYPE (child) == GRUB_EFI_IPV6_DEVICE_PATH_SUBTYPE)
254 && parent
255 && GRUB_EFI_DEVICE_PATH_TYPE (parent) == GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE
256 && GRUB_EFI_DEVICE_PATH_SUBTYPE (parent) == GRUB_EFI_MAC_ADDRESS_DEVICE_PATH_SUBTYPE)
257 continue;
210258
211259 net = grub_efi_open_protocol (*handle, &net_io_guid,
212260 GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
284332 if (! cdp)
285333 continue;
286334 if (grub_efi_compare_device_paths (dp, cdp) != 0)
287 continue;
335 {
336 grub_efi_device_path_t *ldp, *dup_dp, *dup_ldp;
337 int match;
338
339 /* EDK2 UEFI PXE driver creates pseudo devices with type IPv4/IPv6
340 as children of Ethernet card and binds PXE and Load File protocols
341 to it. Loaded Image Device Path protocol will point to these pseudo
342 devices. We skip them when enumerating cards, so here we need to
343 find matching MAC device.
344 */
345 ldp = grub_efi_find_last_device_path (dp);
346 if (GRUB_EFI_DEVICE_PATH_TYPE (ldp) != GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE
347 || (GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) != GRUB_EFI_IPV4_DEVICE_PATH_SUBTYPE
348 && GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) != GRUB_EFI_IPV6_DEVICE_PATH_SUBTYPE))
349 continue;
350 dup_dp = grub_efi_duplicate_device_path (dp);
351 if (!dup_dp)
352 continue;
353 dup_ldp = grub_efi_find_last_device_path (dup_dp);
354 dup_ldp->type = GRUB_EFI_END_DEVICE_PATH_TYPE;
355 dup_ldp->subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE;
356 dup_ldp->length = sizeof (*dup_ldp);
357 match = grub_efi_compare_device_paths (dup_dp, cdp) == 0;
358 grub_free (dup_dp);
359 if (!match)
360 continue;
361 }
288362 pxe = grub_efi_open_protocol (hnd, &pxe_io_guid,
289363 GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
290364 if (! pxe)
15001500 GRUB_EFI_NETWORK_INITIALIZED,
15011501 };
15021502
1503 enum
1504 {
1505 GRUB_EFI_SIMPLE_NETWORK_RECEIVE_UNICAST = 0x01,
1506 GRUB_EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST = 0x02,
1507 GRUB_EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST = 0x04,
1508 GRUB_EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS = 0x08,
1509 GRUB_EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST = 0x10,
1510 };
1511
15031512 struct grub_efi_simple_network
15041513 {
15051514 grub_uint64_t revision;
15061515 grub_efi_status_t (*start) (struct grub_efi_simple_network *this);
1507 void (*stop) (void);
1516 grub_efi_status_t (*stop) (struct grub_efi_simple_network *this);
15081517 grub_efi_status_t (*initialize) (struct grub_efi_simple_network *this,
15091518 grub_efi_uintn_t extra_rx,
15101519 grub_efi_uintn_t extra_tx);
15111520 void (*reset) (void);
1512 void (*shutdown) (void);
1513 void (*receive_filters) (void);
1521 grub_efi_status_t (*shutdown) (struct grub_efi_simple_network *this);
1522 grub_efi_status_t (*receive_filters) (struct grub_efi_simple_network *this,
1523 grub_uint32_t enable,
1524 grub_uint32_t disable,
1525 grub_efi_boolean_t reset_mcast_filter,
1526 grub_efi_uintn_t mcast_filter_count,
1527 grub_efi_mac_address_t *mcast_filter);
15141528 void (*station_address) (void);
15151529 void (*statistics) (void);
15161530 void (*mcastiptomac) (void);
5555 char *EXPORT_FUNC(grub_efi_get_filename) (grub_efi_device_path_t *dp);
5656 grub_efi_device_path_t *
5757 EXPORT_FUNC(grub_efi_get_device_path) (grub_efi_handle_t handle);
58 grub_efi_device_path_t *
59 EXPORT_FUNC(grub_efi_find_last_device_path) (const grub_efi_device_path_t *dp);
60 grub_efi_device_path_t *
61 EXPORT_FUNC(grub_efi_duplicate_device_path) (const grub_efi_device_path_t *dp);
5862 grub_err_t EXPORT_FUNC (grub_efi_finish_boot_services) (grub_efi_uintn_t *outbuf_size, void *outbuf,
5963 grub_efi_uintn_t *map_key,
6064 grub_efi_uintn_t *efi_desc_size,