"Das U-Boot" Source Tree
at master 124 lines 2.9 kB view raw
1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * Bootdev for ethernet (uses PXE) 4 * 5 * Copyright 2021 Google LLC 6 * Written by Simon Glass <sjg@chromium.org> 7 */ 8 9#define LOG_CATEGORY UCLASS_BOOTSTD 10 11#include <bootdev.h> 12#include <bootflow.h> 13#include <command.h> 14#include <bootmeth.h> 15#include <dm.h> 16#include <extlinux.h> 17#include <init.h> 18#include <log.h> 19#include <net.h> 20#include <test/test.h> 21 22static int eth_get_bootflow(struct udevice *dev, struct bootflow_iter *iter, 23 struct bootflow *bflow) 24{ 25 char name[60]; 26 int ret; 27 28 /* Must be an Ethernet device */ 29 ret = bootflow_iter_check_net(iter); 30 if (ret) 31 return log_msg_ret("net", ret); 32 33 ret = bootmeth_check(bflow->method, iter); 34 if (ret) 35 return log_msg_ret("check", ret); 36 37 /* 38 * Like extlinux boot, this assumes there is only one Ethernet device. 39 * In this case, that means that @eth is ignored 40 */ 41 42 snprintf(name, sizeof(name), "%s.%d", dev->name, iter->part); 43 bflow->name = strdup(name); 44 if (!bflow->name) 45 return log_msg_ret("name", -ENOMEM); 46 47 /* See distro_pxe_read_bootflow() for the standard impl of this */ 48 log_debug("dhcp complete - reading bootflow with method '%s'\n", 49 bflow->method->name); 50 ret = bootmeth_read_bootflow(bflow->method, bflow); 51 log_debug("reading bootflow returned %d\n", ret); 52 if (ret) 53 return log_msg_ret("method", ret); 54 55 return 0; 56} 57 58static int eth_bootdev_bind(struct udevice *dev) 59{ 60 struct bootdev_uc_plat *ucp = dev_get_uclass_plat(dev); 61 62 ucp->prio = BOOTDEVP_6_NET_BASE; 63 64 return 0; 65} 66 67/** 68 * eth_bootdev_hunt() - probe all network devices 69 * 70 * Network devices can also come from USB, but that is a higher 71 * priority (BOOTDEVP_5_SCAN_SLOW) than network, so it should have been 72 * enumerated already. If something like 'bootflow scan dhcp' is used, 73 * then the user will need to run 'usb start' first. 74 * 75 * @info: info structure describing this hunter 76 * @show: true to show information from the hunter 77 * 78 * Return: 0 if device found, -EINVAL otherwise 79 */ 80static int eth_bootdev_hunt(struct bootdev_hunter *info, bool show) 81{ 82 int ret; 83 struct udevice *dev = NULL; 84 85 if (!test_eth_enabled()) 86 return 0; 87 88 /* init PCI first since this is often used to provide Ehternet */ 89 if (IS_ENABLED(CONFIG_PCI)) { 90 ret = pci_init(); 91 if (ret) 92 log_warning("Failed to init PCI (%dE)\n", ret); 93 } 94 95 ret = -EINVAL; 96 uclass_foreach_dev_probe(UCLASS_ETH, dev) 97 ret = 0; 98 99 return ret; 100} 101 102struct bootdev_ops eth_bootdev_ops = { 103 .get_bootflow = eth_get_bootflow, 104}; 105 106static const struct udevice_id eth_bootdev_ids[] = { 107 { .compatible = "u-boot,bootdev-eth" }, 108 { } 109}; 110 111U_BOOT_DRIVER(eth_bootdev) = { 112 .name = "eth_bootdev", 113 .id = UCLASS_BOOTDEV, 114 .ops = &eth_bootdev_ops, 115 .bind = eth_bootdev_bind, 116 .of_match = eth_bootdev_ids, 117}; 118 119BOOTDEV_HUNTER(eth_bootdev_hunt) = { 120 .prio = BOOTDEVP_6_NET_BASE, 121 .uclass = UCLASS_ETH, 122 .hunt = eth_bootdev_hunt, 123 .drv = DM_DRIVER_REF(eth_bootdev), 124};