]> git.sur5r.net Git - u-boot/blobdiff - lib/efi_loader/efi_net.c
efi_loader: completely initialize network
[u-boot] / lib / efi_loader / efi_net.c
index 8c5d5b492cab03df847ea6a443c3919cbe592a5b..9afe76cdb31de77783e68338705f97b3f67a6686 100644 (file)
@@ -54,14 +54,46 @@ static efi_status_t EFIAPI efi_net_stop(struct efi_simple_network *this)
        return EFI_EXIT(EFI_SUCCESS);
 }
 
+/*
+ * Initialize network adapter and allocate transmit and receive buffers.
+ *
+ * This function implements the Initialize service of the
+ * EFI_SIMPLE_NETWORK_PROTOCOL. See the Unified Extensible Firmware Interface
+ * (UEFI) specification for details.
+ *
+ * @this:      pointer to the protocol instance
+ * @extra_rx:  extra receive buffer to be allocated
+ * @extra_tx:  extra transmit buffer to be allocated
+ * @return:    status code
+ */
 static efi_status_t EFIAPI efi_net_initialize(struct efi_simple_network *this,
                                              ulong extra_rx, ulong extra_tx)
 {
+       int ret;
+       efi_status_t r = EFI_SUCCESS;
+
        EFI_ENTRY("%p, %lx, %lx", this, extra_rx, extra_tx);
 
-       eth_init();
+       if (!this) {
+               r = EFI_INVALID_PARAMETER;
+               goto error;
+       }
 
-       return EFI_EXIT(EFI_SUCCESS);
+       /* Setup packet buffers */
+       net_init();
+       /* Disable hardware and put it into the reset state */
+       eth_halt();
+       /* Set current device according to environment variables */
+       eth_set_current();
+       /* Get hardware ready for send and receive operations */
+       ret = eth_init();
+       if (ret < 0) {
+               eth_halt();
+               r = EFI_DEVICE_ERROR;
+       }
+
+error:
+       return EFI_EXIT(r);
 }
 
 static efi_status_t EFIAPI efi_net_reset(struct efi_simple_network *this,
@@ -280,20 +312,22 @@ static void EFIAPI efi_network_timer_notify(struct efi_event *event,
 }
 
 /* This gets called from do_bootefi_exec(). */
-int efi_net_register(void)
+efi_status_t efi_net_register(void)
 {
        struct efi_net_obj *netobj;
        efi_status_t r;
 
        if (!eth_get_dev()) {
                /* No eth device active, don't expose any */
-               return 0;
+               return EFI_SUCCESS;
        }
 
        /* We only expose the "active" eth device, so one is enough */
        netobj = calloc(1, sizeof(*netobj));
-       if (!netobj)
-               goto out_of_memory;
+       if (!netobj) {
+               printf("ERROR: Out of memory\n");
+               return EFI_OUT_OF_RESOURCES;
+       }
 
        /* Hook net up to the device list */
        efi_add_handle(&netobj->parent);
@@ -302,15 +336,15 @@ int efi_net_register(void)
        r = efi_add_protocol(netobj->parent.handle, &efi_net_guid,
                             &netobj->net);
        if (r != EFI_SUCCESS)
-               goto out_of_memory;
+               goto failure_to_add_protocol;
        r = efi_add_protocol(netobj->parent.handle, &efi_guid_device_path,
                             efi_dp_from_eth());
        if (r != EFI_SUCCESS)
-               goto out_of_memory;
+               goto failure_to_add_protocol;
        r = efi_add_protocol(netobj->parent.handle, &efi_pxe_guid,
                             &netobj->pxe);
        if (r != EFI_SUCCESS)
-               goto out_of_memory;
+               goto failure_to_add_protocol;
        netobj->net.revision = EFI_SIMPLE_NETWORK_PROTOCOL_REVISION;
        netobj->net.start = efi_net_start;
        netobj->net.stop = efi_net_stop;
@@ -339,7 +373,7 @@ int efi_net_register(void)
         * Create WaitForPacket event.
         */
        r = efi_create_event(EVT_NOTIFY_WAIT, TPL_CALLBACK,
-                            efi_network_timer_notify, NULL,
+                            efi_network_timer_notify, NULL, NULL,
                             &wait_for_packet);
        if (r != EFI_SUCCESS) {
                printf("ERROR: Failed to register network event\n");
@@ -351,9 +385,11 @@ int efi_net_register(void)
         *
         * The notification function is used to check if a new network packet
         * has been received.
+        *
+        * iPXE is running at TPL_CALLBACK most of the time. Use a higher TPL.
         */
-       r = efi_create_event(EVT_TIMER | EVT_NOTIFY_SIGNAL, TPL_CALLBACK,
-                            efi_network_timer_notify, NULL,
+       r = efi_create_event(EVT_TIMER | EVT_NOTIFY_SIGNAL, TPL_NOTIFY,
+                            efi_network_timer_notify, NULL, NULL,
                             &network_timer_event);
        if (r != EFI_SUCCESS) {
                printf("ERROR: Failed to register network event\n");
@@ -366,8 +402,8 @@ int efi_net_register(void)
                return r;
        }
 
-       return 0;
-out_of_memory:
-       printf("ERROR: Out of memory\n");
-       return 1;
+       return EFI_SUCCESS;
+failure_to_add_protocol:
+       printf("ERROR: Failure to add protocol\n");
+       return r;
 }