|
@@ -69,6 +69,35 @@ static EFI_GUID efi_load_file_protocol_guid
|
69
|
69
|
/** List of SNP devices */
|
70
|
70
|
static LIST_HEAD ( efi_snp_devices );
|
71
|
71
|
|
|
72
|
+/**
|
|
73
|
+ * Set EFI SNP mode state
|
|
74
|
+ *
|
|
75
|
+ * @v snp SNP interface
|
|
76
|
+ */
|
|
77
|
+static void efi_snp_set_state ( struct efi_snp_device *snpdev ) {
|
|
78
|
+ struct net_device *netdev = snpdev->netdev;
|
|
79
|
+ EFI_SIMPLE_NETWORK_MODE *mode = &snpdev->mode;
|
|
80
|
+
|
|
81
|
+ /* Calculate state */
|
|
82
|
+ if ( ! snpdev->started ) {
|
|
83
|
+ /* Start() method not called; report as Stopped */
|
|
84
|
+ mode->State = EfiSimpleNetworkStopped;
|
|
85
|
+ } else if ( ! netdev_is_open ( netdev ) ) {
|
|
86
|
+ /* Network device not opened; report as Started */
|
|
87
|
+ mode->State = EfiSimpleNetworkStarted;
|
|
88
|
+ } else if ( ! netdev_rx_frozen ( netdev ) ) {
|
|
89
|
+ /* Network device opened but claimed for use by iPXE; report
|
|
90
|
+ * as Started to inhibit receive polling.
|
|
91
|
+ */
|
|
92
|
+ mode->State = EfiSimpleNetworkStarted;
|
|
93
|
+ } else {
|
|
94
|
+ /* Network device opened and available for use via SNP; report
|
|
95
|
+ * as Initialized.
|
|
96
|
+ */
|
|
97
|
+ mode->State = EfiSimpleNetworkInitialized;
|
|
98
|
+ }
|
|
99
|
+}
|
|
100
|
+
|
72
|
101
|
/**
|
73
|
102
|
* Set EFI SNP mode based on iPXE net device parameters
|
74
|
103
|
*
|
|
@@ -134,7 +163,12 @@ efi_snp_start ( EFI_SIMPLE_NETWORK_PROTOCOL *snp ) {
|
134
|
163
|
|
135
|
164
|
DBGC2 ( snpdev, "SNPDEV %p START\n", snpdev );
|
136
|
165
|
|
137
|
|
- snpdev->mode.State = EfiSimpleNetworkStarted;
|
|
166
|
+ /* Fail if net device is currently claimed for use by iPXE */
|
|
167
|
+ if ( ! netdev_rx_frozen ( snpdev->netdev ) )
|
|
168
|
+ return EFI_NOT_READY;
|
|
169
|
+
|
|
170
|
+ snpdev->started = 1;
|
|
171
|
+ efi_snp_set_state ( snpdev );
|
138
|
172
|
return 0;
|
139
|
173
|
}
|
140
|
174
|
|
|
@@ -151,7 +185,12 @@ efi_snp_stop ( EFI_SIMPLE_NETWORK_PROTOCOL *snp ) {
|
151
|
185
|
|
152
|
186
|
DBGC2 ( snpdev, "SNPDEV %p STOP\n", snpdev );
|
153
|
187
|
|
154
|
|
- snpdev->mode.State = EfiSimpleNetworkStopped;
|
|
188
|
+ /* Fail if net device is currently claimed for use by iPXE */
|
|
189
|
+ if ( ! netdev_rx_frozen ( snpdev->netdev ) )
|
|
190
|
+ return EFI_NOT_READY;
|
|
191
|
+
|
|
192
|
+ snpdev->started = 0;
|
|
193
|
+ efi_snp_set_state ( snpdev );
|
155
|
194
|
return 0;
|
156
|
195
|
}
|
157
|
196
|
|
|
@@ -174,13 +213,17 @@ efi_snp_initialize ( EFI_SIMPLE_NETWORK_PROTOCOL *snp,
|
174
|
213
|
snpdev, ( ( unsigned long ) extra_rx_bufsize ),
|
175
|
214
|
( ( unsigned long ) extra_tx_bufsize ) );
|
176
|
215
|
|
|
216
|
+ /* Fail if net device is currently claimed for use by iPXE */
|
|
217
|
+ if ( ! netdev_rx_frozen ( snpdev->netdev ) )
|
|
218
|
+ return EFI_NOT_READY;
|
|
219
|
+
|
177
|
220
|
if ( ( rc = netdev_open ( snpdev->netdev ) ) != 0 ) {
|
178
|
221
|
DBGC ( snpdev, "SNPDEV %p could not open %s: %s\n",
|
179
|
222
|
snpdev, snpdev->netdev->name, strerror ( rc ) );
|
180
|
223
|
return EFIRC ( rc );
|
181
|
224
|
}
|
|
225
|
+ efi_snp_set_state ( snpdev );
|
182
|
226
|
|
183
|
|
- snpdev->mode.State = EfiSimpleNetworkInitialized;
|
184
|
227
|
return 0;
|
185
|
228
|
}
|
186
|
229
|
|
|
@@ -200,16 +243,20 @@ efi_snp_reset ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, BOOLEAN ext_verify ) {
|
200
|
243
|
DBGC2 ( snpdev, "SNPDEV %p RESET (%s extended verification)\n",
|
201
|
244
|
snpdev, ( ext_verify ? "with" : "without" ) );
|
202
|
245
|
|
|
246
|
+ /* Fail if net device is currently claimed for use by iPXE */
|
|
247
|
+ if ( ! netdev_rx_frozen ( snpdev->netdev ) )
|
|
248
|
+ return EFI_NOT_READY;
|
|
249
|
+
|
203
|
250
|
netdev_close ( snpdev->netdev );
|
204
|
|
- snpdev->mode.State = EfiSimpleNetworkStarted;
|
|
251
|
+ efi_snp_set_state ( snpdev );
|
205
|
252
|
|
206
|
253
|
if ( ( rc = netdev_open ( snpdev->netdev ) ) != 0 ) {
|
207
|
254
|
DBGC ( snpdev, "SNPDEV %p could not reopen %s: %s\n",
|
208
|
255
|
snpdev, snpdev->netdev->name, strerror ( rc ) );
|
209
|
256
|
return EFIRC ( rc );
|
210
|
257
|
}
|
|
258
|
+ efi_snp_set_state ( snpdev );
|
211
|
259
|
|
212
|
|
- snpdev->mode.State = EfiSimpleNetworkInitialized;
|
213
|
260
|
return 0;
|
214
|
261
|
}
|
215
|
262
|
|
|
@@ -226,8 +273,13 @@ efi_snp_shutdown ( EFI_SIMPLE_NETWORK_PROTOCOL *snp ) {
|
226
|
273
|
|
227
|
274
|
DBGC2 ( snpdev, "SNPDEV %p SHUTDOWN\n", snpdev );
|
228
|
275
|
|
|
276
|
+ /* Fail if net device is currently claimed for use by iPXE */
|
|
277
|
+ if ( ! netdev_rx_frozen ( snpdev->netdev ) )
|
|
278
|
+ return EFI_NOT_READY;
|
|
279
|
+
|
229
|
280
|
netdev_close ( snpdev->netdev );
|
230
|
|
- snpdev->mode.State = EfiSimpleNetworkStarted;
|
|
281
|
+ efi_snp_set_state ( snpdev );
|
|
282
|
+
|
231
|
283
|
return 0;
|
232
|
284
|
}
|
233
|
285
|
|
|
@@ -258,6 +310,10 @@ efi_snp_receive_filters ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, UINT32 enable,
|
258
|
310
|
snpdev->netdev->ll_protocol->ll_addr_len );
|
259
|
311
|
}
|
260
|
312
|
|
|
313
|
+ /* Fail if net device is currently claimed for use by iPXE */
|
|
314
|
+ if ( ! netdev_rx_frozen ( snpdev->netdev ) )
|
|
315
|
+ return EFI_NOT_READY;
|
|
316
|
+
|
261
|
317
|
/* Lie through our teeth, otherwise MNP refuses to accept us */
|
262
|
318
|
return 0;
|
263
|
319
|
}
|
|
@@ -280,6 +336,10 @@ efi_snp_station_address ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, BOOLEAN reset,
|
280
|
336
|
DBGC2 ( snpdev, "SNPDEV %p STATION_ADDRESS %s\n", snpdev,
|
281
|
337
|
( reset ? "reset" : ll_protocol->ntoa ( new ) ) );
|
282
|
338
|
|
|
339
|
+ /* Fail if net device is currently claimed for use by iPXE */
|
|
340
|
+ if ( ! netdev_rx_frozen ( snpdev->netdev ) )
|
|
341
|
+ return EFI_NOT_READY;
|
|
342
|
+
|
283
|
343
|
/* Set the MAC address */
|
284
|
344
|
if ( reset )
|
285
|
345
|
new = &snpdev->mode.PermanentAddress;
|
|
@@ -313,6 +373,10 @@ efi_snp_statistics ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, BOOLEAN reset,
|
313
|
373
|
DBGC2 ( snpdev, "SNPDEV %p STATISTICS%s", snpdev,
|
314
|
374
|
( reset ? " reset" : "" ) );
|
315
|
375
|
|
|
376
|
+ /* Fail if net device is currently claimed for use by iPXE */
|
|
377
|
+ if ( ! netdev_rx_frozen ( snpdev->netdev ) )
|
|
378
|
+ return EFI_NOT_READY;
|
|
379
|
+
|
316
|
380
|
/* Gather statistics */
|
317
|
381
|
memset ( &stats_buf, 0, sizeof ( stats_buf ) );
|
318
|
382
|
stats_buf.TxGoodFrames = snpdev->netdev->tx_stats.good;
|
|
@@ -361,6 +425,10 @@ efi_snp_mcast_ip_to_mac ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, BOOLEAN ipv6,
|
361
|
425
|
inet_ntoa ( *( ( struct in_addr * ) ip ) ) );
|
362
|
426
|
DBGC2 ( snpdev, "SNPDEV %p MCAST_IP_TO_MAC %s\n", snpdev, ip_str );
|
363
|
427
|
|
|
428
|
+ /* Fail if net device is currently claimed for use by iPXE */
|
|
429
|
+ if ( ! netdev_rx_frozen ( snpdev->netdev ) )
|
|
430
|
+ return EFI_NOT_READY;
|
|
431
|
+
|
364
|
432
|
/* Try to hash the address */
|
365
|
433
|
if ( ( rc = ll_protocol->mc_hash ( ( ipv6 ? AF_INET6 : AF_INET ),
|
366
|
434
|
ip, mac ) ) != 0 ) {
|
|
@@ -394,6 +462,10 @@ efi_snp_nvdata ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, BOOLEAN read,
|
394
|
462
|
if ( ! read )
|
395
|
463
|
DBGC2_HDA ( snpdev, offset, data, len );
|
396
|
464
|
|
|
465
|
+ /* Fail if net device is currently claimed for use by iPXE */
|
|
466
|
+ if ( ! netdev_rx_frozen ( snpdev->netdev ) )
|
|
467
|
+ return EFI_NOT_READY;
|
|
468
|
+
|
397
|
469
|
return EFI_UNSUPPORTED;
|
398
|
470
|
}
|
399
|
471
|
|
|
@@ -413,6 +485,10 @@ efi_snp_get_status ( EFI_SIMPLE_NETWORK_PROTOCOL *snp,
|
413
|
485
|
|
414
|
486
|
DBGC2 ( snpdev, "SNPDEV %p GET_STATUS", snpdev );
|
415
|
487
|
|
|
488
|
+ /* Fail if net device is currently claimed for use by iPXE */
|
|
489
|
+ if ( ! netdev_rx_frozen ( snpdev->netdev ) )
|
|
490
|
+ return EFI_NOT_READY;
|
|
491
|
+
|
416
|
492
|
/* Poll the network device */
|
417
|
493
|
efi_snp_poll ( snpdev );
|
418
|
494
|
|
|
@@ -508,6 +584,10 @@ efi_snp_transmit ( EFI_SIMPLE_NETWORK_PROTOCOL *snp,
|
508
|
584
|
}
|
509
|
585
|
DBGC2 ( snpdev, "\n" );
|
510
|
586
|
|
|
587
|
+ /* Fail if net device is currently claimed for use by iPXE */
|
|
588
|
+ if ( ! netdev_rx_frozen ( snpdev->netdev ) )
|
|
589
|
+ return EFI_NOT_READY;
|
|
590
|
+
|
511
|
591
|
/* Sanity checks */
|
512
|
592
|
if ( ll_header_len ) {
|
513
|
593
|
if ( ll_header_len != ll_protocol->ll_header_len ) {
|
|
@@ -616,6 +696,10 @@ efi_snp_receive ( EFI_SIMPLE_NETWORK_PROTOCOL *snp,
|
616
|
696
|
DBGC2 ( snpdev, "SNPDEV %p RECEIVE %p(+%lx)", snpdev, data,
|
617
|
697
|
( ( unsigned long ) *len ) );
|
618
|
698
|
|
|
699
|
+ /* Fail if net device is currently claimed for use by iPXE */
|
|
700
|
+ if ( ! netdev_rx_frozen ( snpdev->netdev ) )
|
|
701
|
+ return EFI_NOT_READY;
|
|
702
|
+
|
619
|
703
|
/* Poll the network device */
|
620
|
704
|
efi_snp_poll ( snpdev );
|
621
|
705
|
|
|
@@ -655,7 +739,7 @@ efi_snp_receive ( EFI_SIMPLE_NETWORK_PROTOCOL *snp,
|
655
|
739
|
|
656
|
740
|
out_bad_ll_header:
|
657
|
741
|
free_iob ( iobuf );
|
658
|
|
-out_no_packet:
|
|
742
|
+ out_no_packet:
|
659
|
743
|
return EFIRC ( rc );
|
660
|
744
|
}
|
661
|
745
|
|
|
@@ -676,6 +760,10 @@ static VOID EFIAPI efi_snp_wait_for_packet ( EFI_EVENT event,
|
676
|
760
|
if ( ! netdev_is_open ( snpdev->netdev ) )
|
677
|
761
|
return;
|
678
|
762
|
|
|
763
|
+ /* Do nothing if net device is currently claimed for use by iPXE */
|
|
764
|
+ if ( ! netdev_rx_frozen ( snpdev->netdev ) )
|
|
765
|
+ return;
|
|
766
|
+
|
679
|
767
|
/* Poll the network device */
|
680
|
768
|
efi_snp_poll ( snpdev );
|
681
|
769
|
|
|
@@ -785,9 +873,15 @@ efi_snp_load_file ( EFI_LOAD_FILE_PROTOCOL *load_file,
|
785
|
873
|
return EFI_UNSUPPORTED;
|
786
|
874
|
}
|
787
|
875
|
|
|
876
|
+ /* Claim network devices for use by iPXE */
|
|
877
|
+ efi_snp_claim();
|
|
878
|
+
|
788
|
879
|
/* Boot from network device */
|
789
|
880
|
ipxe ( netdev );
|
790
|
881
|
|
|
882
|
+ /* Release network devices for use via SNP */
|
|
883
|
+ efi_snp_release();
|
|
884
|
+
|
791
|
885
|
/* Assume boot process was aborted */
|
792
|
886
|
return EFI_ABORTED;
|
793
|
887
|
}
|
|
@@ -1011,6 +1105,9 @@ static void efi_snp_notify ( struct net_device *netdev ) {
|
1011
|
1105
|
( netdev_link_ok ( netdev ) ? TRUE : FALSE );
|
1012
|
1106
|
DBGC ( snpdev, "SNPDEV %p link is %s\n", snpdev,
|
1013
|
1107
|
( snpdev->mode.MediaPresent ? "up" : "down" ) );
|
|
1108
|
+
|
|
1109
|
+ /* Update mode state */
|
|
1110
|
+ efi_snp_set_state ( snpdev );
|
1014
|
1111
|
}
|
1015
|
1112
|
|
1016
|
1113
|
/**
|
|
@@ -1069,3 +1166,25 @@ struct efi_snp_device * last_opened_snpdev ( void ) {
|
1069
|
1166
|
|
1070
|
1167
|
return efi_snp_demux ( netdev );
|
1071
|
1168
|
}
|
|
1169
|
+
|
|
1170
|
+/**
|
|
1171
|
+ * Claim network devices for use by iPXE
|
|
1172
|
+ *
|
|
1173
|
+ */
|
|
1174
|
+void efi_snp_claim ( void ) {
|
|
1175
|
+ struct net_device *netdev;
|
|
1176
|
+
|
|
1177
|
+ for_each_netdev ( netdev )
|
|
1178
|
+ netdev_rx_unfreeze ( netdev );
|
|
1179
|
+}
|
|
1180
|
+
|
|
1181
|
+/**
|
|
1182
|
+ * Release network devices for use via SNP
|
|
1183
|
+ *
|
|
1184
|
+ */
|
|
1185
|
+void efi_snp_release ( void ) {
|
|
1186
|
+ struct net_device *netdev;
|
|
1187
|
+
|
|
1188
|
+ for_each_netdev ( netdev )
|
|
1189
|
+ netdev_rx_freeze ( netdev );
|
|
1190
|
+}
|