* Initializing MAC address at run-time
@ 2017-01-18 14:03 Mason
[not found] ` <e083ed68-0e8e-380e-23bd-5ad387c88575-GANU6spQydw@public.gmane.org>
2017-01-18 18:54 ` Uwe Kleine-König
0 siblings, 2 replies; 6+ messages in thread
From: Mason @ 2017-01-18 14:03 UTC (permalink / raw)
To: Linux ARM, DT, netdev
Cc: Mark Rutland, Thibaud Cornic, Uwe Kleine-Konig, Arnd Bergmann,
Kevin Hilman
Hello,
When my system boots up, eth0 is given a seemingly random MAC address.
[ 0.950734] nb8800 26000.ethernet eth0: MAC address ba:de:d6:38:b8:38
[ 0.957334] nb8800 26000.ethernet eth0: MAC address 6e:f1:48:de:d6:c4
The DT node for eth0 is:
eth0: ethernet@26000 {
compatible = "sigma,smp8734-ethernet";
reg = <0x26000 0x800>;
interrupts = <38 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clkgen SYS_CLK>;
};
Documentation/devicetree/bindings/net/ethernet.txt mentions
- local-mac-address: array of 6 bytes, specifies the MAC address that was
assigned to the network device;
And indeed, if I define this property, eth0 ends up with the MAC address
I specify in the device tree. But of course, I don't want all my boards
to share the same MAC address. Every interface has a unique MAC address.
In fact, the boot loader (not Uboot, a custom non-DT boot loader) stores
the MAC address somewhere in MMIO space, in some weird custom format.
So, at init, I can find the MAC address, and dynamically insert the
"local-mac-address" property in the eth0 node.
Is there another (better) way to do this?
I'll post my code below, for illustration purpose.
Mark suggested this can be done from user-space, but I can't do that,
because I'm using an NFS rootfs, so I need the network before I even
have a user-space. And the DHCP server is configured to serve different
root filesystems, based on the MAC address.
I need to do something similar with the NAND partitions. The boot loader
stores the partition offsets somewhere, and I need to pass this info
to the NAND framework, so I assumed that inserting the corresponding
properties at run-time was the correct way to do it.
Regards.
#include <linux/of.h>
#include <linux/io.h>
#include <asm/unaligned.h>
#define XENV_LRRW_ADDR 0x61a00
#define XENV_LRRW_SIZE 628
static u8 xenv[XENV_LRRW_SIZE] __initdata;
static void __init *xenv_lookup(void *addr, const char *key, int keylen)
{
u32 len = le32_to_cpup(addr);
void *end = addr + len;
if (len > XENV_LRRW_SIZE)
return NULL;
for (addr += 36; addr < end; addr += len)
{
len = get_unaligned_be16(addr) & 0xfff;
if (strcmp(key, addr + 2) == 0)
return addr + 2 + keylen;
}
return NULL;
}
static struct property prop;
static u8 mac[6];
static const char mac_lo[] __initconst = "lrrw.maclo";
static const char mac_hi[] __initconst = "lrrw.machi";
static int __init tango_get_mac_address(void *xenv)
{
struct device_node *np = of_find_node_by_path("eth0");
u8 *lo = xenv_lookup(xenv, mac_lo, sizeof mac_lo);
u8 *hi = xenv_lookup(xenv, mac_hi, sizeof mac_hi);
if (np == NULL || lo == NULL || hi == NULL) return -ENODEV;
mac[0] = hi[1];
mac[1] = hi[0];
mac[2] = lo[3];
mac[3] = lo[2];
mac[4] = lo[1];
mac[5] = lo[0];
prop.name = "local-mac-address";
prop.length = sizeof mac;
prop.value = mac;
return of_update_property(np, &prop);
}
static int __init mac_fixup(void)
{
void __iomem *xenv_orig = ioremap(XENV_LRRW_ADDR, XENV_LRRW_SIZE);
memcpy_fromio(xenv, xenv_orig, XENV_LRRW_SIZE);
iounmap(xenv_orig);
return tango_get_mac_address(xenv);
}
device_initcall(mac_fixup);
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: Initializing MAC address at run-time
[not found] ` <e083ed68-0e8e-380e-23bd-5ad387c88575-GANU6spQydw@public.gmane.org>
@ 2017-01-18 14:45 ` Mark Rutland
2017-01-18 15:35 ` Robin Murphy
0 siblings, 1 reply; 6+ messages in thread
From: Mark Rutland @ 2017-01-18 14:45 UTC (permalink / raw)
To: Mason
Cc: Linux ARM, DT, netdev, Arnd Bergmann, Kevin Hilman,
Uwe Kleine-Konig, Thibaud Cornic
On Wed, Jan 18, 2017 at 03:03:57PM +0100, Mason wrote:
> Hello,
>
> When my system boots up, eth0 is given a seemingly random MAC address.
>
> [ 0.950734] nb8800 26000.ethernet eth0: MAC address ba:de:d6:38:b8:38
> [ 0.957334] nb8800 26000.ethernet eth0: MAC address 6e:f1:48:de:d6:c4
>
>
> The DT node for eth0 is:
>
> eth0: ethernet@26000 {
> compatible = "sigma,smp8734-ethernet";
> reg = <0x26000 0x800>;
> interrupts = <38 IRQ_TYPE_LEVEL_HIGH>;
> clocks = <&clkgen SYS_CLK>;
> };
>
> Documentation/devicetree/bindings/net/ethernet.txt mentions
> - local-mac-address: array of 6 bytes, specifies the MAC address that was
> assigned to the network device;
>
> And indeed, if I define this property, eth0 ends up with the MAC address
> I specify in the device tree. But of course, I don't want all my boards
> to share the same MAC address. Every interface has a unique MAC address.
>
> In fact, the boot loader (not Uboot, a custom non-DT boot loader) stores
> the MAC address somewhere in MMIO space, in some weird custom format.
>
> So, at init, I can find the MAC address, and dynamically insert the
> "local-mac-address" property in the eth0 node.
To me it sounds very convoluted to do this from the kernel, to pass
information back to itself. I don't think this is the best way to handle
this.
> Is there another (better) way to do this?
>
> I'll post my code below, for illustration purpose.
>
> Mark suggested this can be done from user-space, but I can't do that,
> because I'm using an NFS rootfs, so I need the network before I even
> have a user-space. And the DHCP server is configured to serve different
> root filesystems, based on the MAC address.
That's not quite what I said. I asked whether your information was
coming from userspace or from a kernel driver.
My suggestion was that this should be done in the probe path somehow,
by describing the relationship between the ethernet controller and the
device containing the MAC information.
e.g. on the ethernet device, have a phandle (and perhaps some other
args) describinng the device containing the MAC, and how to extract it.
That way, in the ethernet probe path we can go and look up the MAC
address from the provider of that information.
> I need to do something similar with the NAND partitions. The boot loader
> stores the partition offsets somewhere, and I need to pass this info
> to the NAND framework, so I assumed that inserting the corresponding
> properties at run-time was the correct way to do it.
I would say similar could happen here.
Thanks,
Mark.
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: Initializing MAC address at run-time
2017-01-18 14:45 ` Mark Rutland
@ 2017-01-18 15:35 ` Robin Murphy
0 siblings, 0 replies; 6+ messages in thread
From: Robin Murphy @ 2017-01-18 15:35 UTC (permalink / raw)
To: Mason
Cc: Mark Rutland, DT, Arnd Bergmann, Kevin Hilman, netdev,
Thibaud Cornic, Uwe Kleine-Konig, Linux ARM
On 18/01/17 14:45, Mark Rutland wrote:
> On Wed, Jan 18, 2017 at 03:03:57PM +0100, Mason wrote:
>> Hello,
>>
>> When my system boots up, eth0 is given a seemingly random MAC address.
>>
>> [ 0.950734] nb8800 26000.ethernet eth0: MAC address ba:de:d6:38:b8:38
>> [ 0.957334] nb8800 26000.ethernet eth0: MAC address 6e:f1:48:de:d6:c4
>>
>>
>> The DT node for eth0 is:
>>
>> eth0: ethernet@26000 {
>> compatible = "sigma,smp8734-ethernet";
>> reg = <0x26000 0x800>;
>> interrupts = <38 IRQ_TYPE_LEVEL_HIGH>;
>> clocks = <&clkgen SYS_CLK>;
>> };
>>
>> Documentation/devicetree/bindings/net/ethernet.txt mentions
>> - local-mac-address: array of 6 bytes, specifies the MAC address that was
>> assigned to the network device;
>>
>> And indeed, if I define this property, eth0 ends up with the MAC address
>> I specify in the device tree. But of course, I don't want all my boards
>> to share the same MAC address. Every interface has a unique MAC address.
>>
>> In fact, the boot loader (not Uboot, a custom non-DT boot loader) stores
>> the MAC address somewhere in MMIO space, in some weird custom format.
>>
>> So, at init, I can find the MAC address, and dynamically insert the
>> "local-mac-address" property in the eth0 node.
>
> To me it sounds very convoluted to do this from the kernel, to pass
> information back to itself. I don't think this is the best way to handle
> this.
>
>> Is there another (better) way to do this?
>>
>> I'll post my code below, for illustration purpose.
>>
>> Mark suggested this can be done from user-space, but I can't do that,
>> because I'm using an NFS rootfs, so I need the network before I even
>> have a user-space. And the DHCP server is configured to serve different
>> root filesystems, based on the MAC address.
>
> That's not quite what I said. I asked whether your information was
> coming from userspace or from a kernel driver.
>
> My suggestion was that this should be done in the probe path somehow,
> by describing the relationship between the ethernet controller and the
> device containing the MAC information.
>
> e.g. on the ethernet device, have a phandle (and perhaps some other
> args) describinng the device containing the MAC, and how to extract it.
>
> That way, in the ethernet probe path we can go and look up the MAC
> address from the provider of that information.
See Documentation/devicetree/bindings/mfd/syscon.txt and
bindings/drivers with syscon dependencies. Essentially, you would use a
syscon node to describe "somewhere in MMIO space", then your ethernet
driver probe routine simply grabs the regmap, pulls out the MAC and goes
from there.
Be warned that the above represents the totality of my technical
knowledge on the subject ;) My experience is in hacking up DTs for
drivers which already use this mechanism, rather than in implementing it.
Robin.
>> I need to do something similar with the NAND partitions. The boot loader
>> stores the partition offsets somewhere, and I need to pass this info
>> to the NAND framework, so I assumed that inserting the corresponding
>> properties at run-time was the correct way to do it.
>
> I would say similar could happen here.
>
> Thanks,
> Mark.
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: Initializing MAC address at run-time
2017-01-18 14:03 Initializing MAC address at run-time Mason
[not found] ` <e083ed68-0e8e-380e-23bd-5ad387c88575-GANU6spQydw@public.gmane.org>
@ 2017-01-18 18:54 ` Uwe Kleine-König
2017-01-19 15:31 ` Mason
1 sibling, 1 reply; 6+ messages in thread
From: Uwe Kleine-König @ 2017-01-18 18:54 UTC (permalink / raw)
To: Mason
Cc: Mark Rutland, DT, Arnd Bergmann, Kevin Hilman, netdev,
Thibaud Cornic, Linux ARM
Hello,
On Wed, Jan 18, 2017 at 03:03:57PM +0100, Mason wrote:
> When my system boots up, eth0 is given a seemingly random MAC address.
>
> [ 0.950734] nb8800 26000.ethernet eth0: MAC address ba:de:d6:38:b8:38
> [ 0.957334] nb8800 26000.ethernet eth0: MAC address 6e:f1:48:de:d6:c4
>
>
> The DT node for eth0 is:
>
> eth0: ethernet@26000 {
> compatible = "sigma,smp8734-ethernet";
> reg = <0x26000 0x800>;
> interrupts = <38 IRQ_TYPE_LEVEL_HIGH>;
> clocks = <&clkgen SYS_CLK>;
> };
>
> Documentation/devicetree/bindings/net/ethernet.txt mentions
> - local-mac-address: array of 6 bytes, specifies the MAC address that was
> assigned to the network device;
>
> And indeed, if I define this property, eth0 ends up with the MAC address
> I specify in the device tree. But of course, I don't want all my boards
> to share the same MAC address. Every interface has a unique MAC address.
>
> In fact, the boot loader (not Uboot, a custom non-DT boot loader) stores
> the MAC address somewhere in MMIO space, in some weird custom format.
Where does your machine get the dtb from? You write it to the boot
medium at a certain point of time I assume. So AFAICT you have the
following options (in no particular order):
a) Describe in the dtb how to find out how the MAC address is stored
(already pointed out Mark and Robin)
b) Make your bootloader dt aware and let it provide the
local-mac-address property.
c) Adapt the dtb before it is written to the boot medium.
d) Let the bootloader configure the device and teach the driver to pick
up the mac from the device's address space.
e) Accept that the mac address is random during development, and make
Userspace configure the MAC address, which is early enough for
production use.
Not sure d) is considered ok today, but some drivers have this feature.
I'd say b) is the best choice.
> I need to do something similar with the NAND partitions. The boot loader
> stores the partition offsets somewhere, and I need to pass this info
> to the NAND framework, so I assumed that inserting the corresponding
> properties at run-time was the correct way to do it.
The list of options here is similar to the list above. d) doesn't work,
but instead you can pass the partitioning on the kernel commandline.
Best regards
Uwe
--
Pengutronix e.K. | Uwe Kleine-König |
Industrial Linux Solutions | http://www.pengutronix.de/ |
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: Initializing MAC address at run-time
2017-01-18 18:54 ` Uwe Kleine-König
@ 2017-01-19 15:31 ` Mason
2017-01-19 16:26 ` Uwe Kleine-König
0 siblings, 1 reply; 6+ messages in thread
From: Mason @ 2017-01-19 15:31 UTC (permalink / raw)
To: Uwe Kleine-König
Cc: Mark Rutland, DT, Arnd Bergmann, Kevin Hilman, netdev,
Thibaud Cornic, Linux ARM
Hello Uwe,
On 18/01/2017 19:54, Uwe Kleine-König wrote:
> On Wed, Jan 18, 2017 at 03:03:57PM +0100, Mason wrote:
>
>> When my system boots up, eth0 is given a seemingly random MAC address.
>>
>> [ 0.950734] nb8800 26000.ethernet eth0: MAC address ba:de:d6:38:b8:38
>> [ 0.957334] nb8800 26000.ethernet eth0: MAC address 6e:f1:48:de:d6:c4
>>
>>
>> The DT node for eth0 is:
>>
>> eth0: ethernet@26000 {
>> compatible = "sigma,smp8734-ethernet";
>> reg = <0x26000 0x800>;
>> interrupts = <38 IRQ_TYPE_LEVEL_HIGH>;
>> clocks = <&clkgen SYS_CLK>;
>> };
>>
>> Documentation/devicetree/bindings/net/ethernet.txt mentions
>> - local-mac-address: array of 6 bytes, specifies the MAC address that was
>> assigned to the network device;
>>
>> And indeed, if I define this property, eth0 ends up with the MAC address
>> I specify in the device tree. But of course, I don't want all my boards
>> to share the same MAC address. Every interface has a unique MAC address.
>>
>> In fact, the boot loader (not Uboot, a custom non-DT boot loader) stores
>> the MAC address somewhere in MMIO space, in some weird custom format.
>
> Where does your machine get the dtb from? You write it to the boot
> medium at a certain point of time I assume.
The DTB is appended to the kernel uImage.
(It's never written to the board's storage.)
> So AFAICT you have the following options (in no particular order):
>
> a) Describe in the dtb how to find out how the MAC address is stored
> (already pointed out Mark and Robin)
> b) Make your bootloader dt aware and let it provide the
> local-mac-address property.
Do you agree that such boot loader would execute code that is roughly
identical to the one posted for illustration purposes?
1. find the MAC address to use for eth0
2. find the eth0 node in the DT
3. insert the right prop in the eth0 node
In which case, it seems a waste to add the DT library to the boot
loader, when the operation can be done in Linux, which requires the
DT library anyway. (Additionally, adding DT support to some custom
legacy boot loader might be a complex task.)
> c) Adapt the dtb before it is written to the boot medium.
This is not applicable, as the DTB is not written to the board.
> d) Let the bootloader configure the device and teach the driver to pick
> up the mac from the device's address space.
I'm not sure what you call "the device" ?
The local RAM where the MAC is stored? the eth controller?
> e) Accept that the mac address is random during development, and make
> Userspace configure the MAC address, which is early enough for
> production use.
During development, some devs configure the DHCP server to provide
a specific uImage and/or rootfs to their board, based on the MAC
address. This scheme would fall apart with a random MAC.
> Not sure d) is considered ok today, but some drivers have this feature.
> I'd say b) is the best choice.
In my mind, doing it early in Linux is similar in spirit to doing it
at the boot loader stage, in that it's neatly separated from the rest
of the setup.
>> I need to do something similar with the NAND partitions. The boot loader
>> stores the partition offsets somewhere, and I need to pass this info
>> to the NAND framework, so I assumed that inserting the corresponding
>> properties at run-time was the correct way to do it.
>
> The list of options here is similar to the list above. d) doesn't work,
> but instead you can pass the partitioning on the kernel commandline.
Yes, I will test the command line approach. Thanks.
Regards.
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: Initializing MAC address at run-time
2017-01-19 15:31 ` Mason
@ 2017-01-19 16:26 ` Uwe Kleine-König
0 siblings, 0 replies; 6+ messages in thread
From: Uwe Kleine-König @ 2017-01-19 16:26 UTC (permalink / raw)
To: Mason
Cc: Mark Rutland, DT, Arnd Bergmann, Kevin Hilman, netdev,
Thibaud Cornic, Linux ARM
Hello,
On Thu, Jan 19, 2017 at 04:31:56PM +0100, Mason wrote:
> Do you agree that such boot loader would execute code that is roughly
> identical to the one posted for illustration purposes?
> 1. find the MAC address to use for eth0
> 2. find the eth0 node in the DT
> 3. insert the right prop in the eth0 node
yes.
> In which case, it seems a waste to add the DT library to the boot
> loader, when the operation can be done in Linux, which requires the
> DT library anyway. (Additionally, adding DT support to some custom
> legacy boot loader might be a complex task.)
With this reasoning you can discuss away the bootloader. Linux relies on
a bootloader for a reason. It's there to initialize RAM and some further
things that Linux might not be able to and provide a machine description
to Linux (either in form of a dtb or an ATAG list) such that Linux
doesn't need to fiddle with machine specific stuff in early init code.
> > c) Adapt the dtb before it is written to the boot medium.
>
> This is not applicable, as the DTB is not written to the board.
Ah, then adapt the dtb before it is put into the tftp folder.
> > d) Let the bootloader configure the device and teach the driver to pick
> > up the mac from the device's address space.
>
> I'm not sure what you call "the device" ?
The network device. IIRC the fec driver checks if there is something
configured in the two registers configuring the MAC before falling back
to a random MAC.
> > e) Accept that the mac address is random during development, and make
> > Userspace configure the MAC address, which is early enough for
> > production use.
>
> During development, some devs configure the DHCP server to provide
> a specific uImage and/or rootfs to their board, based on the MAC
> address. This scheme would fall apart with a random MAC.
>
> > Not sure d) is considered ok today, but some drivers have this feature.
> > I'd say b) is the best choice.
>
> In my mind, doing it early in Linux is similar in spirit to doing it
> at the boot loader stage, in that it's neatly separated from the rest
> of the setup.
Sure you can do this. But it won't be accepted mainline for sure.
Best regards
Uwe
--
Pengutronix e.K. | Uwe Kleine-König |
Industrial Linux Solutions | http://www.pengutronix.de/ |
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2017-01-19 16:26 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-01-18 14:03 Initializing MAC address at run-time Mason
[not found] ` <e083ed68-0e8e-380e-23bd-5ad387c88575-GANU6spQydw@public.gmane.org>
2017-01-18 14:45 ` Mark Rutland
2017-01-18 15:35 ` Robin Murphy
2017-01-18 18:54 ` Uwe Kleine-König
2017-01-19 15:31 ` Mason
2017-01-19 16:26 ` Uwe Kleine-König
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).