diff mbox series

[v4] test/py: net_boot: Add test cases for net boot

Message ID d08d45f50dcdfb70e22a27cf13a990bcc2c020fc.1714738132.git.love.kumar@amd.com
State Changes Requested
Delegated to: Tom Rini
Headers show
Series [v4] test/py: net_boot: Add test cases for net boot | expand

Commit Message

Love Kumar May 3, 2024, 12:09 p.m. UTC
Add tests for booting image using tftpboot/pxe boot commands, tftpboot
boot case loads the FIT image into DDR and boots using bootm command
whereas pxe boot cases downloads the pxe configuration file from the
TFTP server and interprets it to boot the images mentioned in the pxe
configurations file.
This test relies on boardenv_* containing configuration values including
the parameter 'pattern'. tftpboot/pxe boot cases boots the Linux till the
boot log pattern value is matched. For example, if the parameter
'pattern' is defined as 'login:', it will boot till login prompt.

Signed-off-by: Love Kumar <love.kumar@amd.com>
---
Changes in v2:
 - Expand commit message
Changes in v3:
 - Add the config option to skip the test
 - Remove imi command to check FIT image config
 - Configure static networking only if DHCP fails
Changes in v4:
 - Use configured timeout for tftpboot
---
 test/py/tests/test_net_boot.py | 394 +++++++++++++++++++++++++++++++++
 1 file changed, 394 insertions(+)
 create mode 100644 test/py/tests/test_net_boot.py

Comments

Tom Rini May 3, 2024, 8:07 p.m. UTC | #1
On Fri, May 03, 2024 at 05:39:46PM +0530, Love Kumar wrote:

> Add tests for booting image using tftpboot/pxe boot commands, tftpboot
> boot case loads the FIT image into DDR and boots using bootm command
> whereas pxe boot cases downloads the pxe configuration file from the
> TFTP server and interprets it to boot the images mentioned in the pxe
> configurations file.
> This test relies on boardenv_* containing configuration values including
> the parameter 'pattern'. tftpboot/pxe boot cases boots the Linux till the
> boot log pattern value is matched. For example, if the parameter
> 'pattern' is defined as 'login:', it will boot till login prompt.
> 
> Signed-off-by: Love Kumar <love.kumar@amd.com>
> ---
> Changes in v2:
>  - Expand commit message
> Changes in v3:
>  - Add the config option to skip the test
>  - Remove imi command to check FIT image config
>  - Configure static networking only if DHCP fails
> Changes in v4:
>  - Use configured timeout for tftpboot

Getting closer! Can we make this more robust and check for failure strings too?
For example:
U-Boot> tftpboot 200000 v6.6/image.fit.nocomp
Waiting for Ethernet connection... done.
Using smsc95xx_eth device
TFTP from server 192.168.1.10; our IP address is 192.168.1.100
Filename 'v6.6/image.fit.nocomp'.
Load address: 0x200000
Loading: ##################################################  82 MiB
         2.7 MiB/s
done
Bytes transferred = 85984256 (5200400 hex)
U-Boot> U-Boot> crc32 200000 $filesize
CRC32 for 00200000 ... 054003ff ==> 754c839a
U-Boot> U-Boot> bootm 200000
Wrong Image Type for bootm command
ERROR -91: can't get kernel image!
U-Boot>

This only fails when we hit timeout.
Tom Rini May 3, 2024, 8:18 p.m. UTC | #2
On Fri, May 03, 2024 at 05:39:46PM +0530, Love Kumar wrote:

> Add tests for booting image using tftpboot/pxe boot commands, tftpboot
> boot case loads the FIT image into DDR and boots using bootm command
> whereas pxe boot cases downloads the pxe configuration file from the
> TFTP server and interprets it to boot the images mentioned in the pxe
> configurations file.
> This test relies on boardenv_* containing configuration values including
> the parameter 'pattern'. tftpboot/pxe boot cases boots the Linux till the
> boot log pattern value is matched. For example, if the parameter
> 'pattern' is defined as 'login:', it will boot till login prompt.
> 
> Signed-off-by: Love Kumar <love.kumar@amd.com>

I'm not quite sure where the problem is, next. After enabling FIT image
support in my build so I can use the image I have on hand:
U-Boot> tftpboot 200000 v6.6/image.fit.nocomp
Waiting for Ethernet connection... done.
Using smsc95xx_eth device
TFTP from server 192.168.1.10; our IP address is 192.168.1.100
Filename 'v6.6/image.fit.nocomp'.
Load address: 0x200000
Loading: ##################################################  82 MiB
         3.2 MiB/s
done
Bytes transferred = 85984256 (5200400 hex)
U-Boot> U-Boot> crc32 200000 $filesize
CRC32 for 00200000 ... 054003ff ==> 754c839a
U-Boot> U-Boot> bootm 200000
## Loading kernel from FIT Image at 00200000 ...
Could not find configuration node
ERROR -2: can't get kernel image!
U-Boot>

And in u_boot_boardenv_rpi_arm64.py:
env__tftp_boot_test_skip = False

env__net_tftp_bootable_file = {
    'fn': 'v6.6/image.fit.nocomp',
    'addr': 0x00200000,
    'size': 85984256,
    'crc32': '754c839a',
    'pattern': 'Linux',
    'config': 'conf-852',
}

But it's not trying to boot conf-852 but instead just passing the
address. This image lacks a default config, which your example has and I
think is why the tests work in your case.
Love Kumar May 7, 2024, 5:52 a.m. UTC | #3
On 04/05/24 1:48 am, Tom Rini wrote:
> On Fri, May 03, 2024 at 05:39:46PM +0530, Love Kumar wrote:
> 
>> Add tests for booting image using tftpboot/pxe boot commands, tftpboot
>> boot case loads the FIT image into DDR and boots using bootm command
>> whereas pxe boot cases downloads the pxe configuration file from the
>> TFTP server and interprets it to boot the images mentioned in the pxe
>> configurations file.
>> This test relies on boardenv_* containing configuration values including
>> the parameter 'pattern'. tftpboot/pxe boot cases boots the Linux till the
>> boot log pattern value is matched. For example, if the parameter
>> 'pattern' is defined as 'login:', it will boot till login prompt.
>>
>> Signed-off-by: Love Kumar <love.kumar@amd.com>
> 
> I'm not quite sure where the problem is, next. After enabling FIT image
> support in my build so I can use the image I have on hand:
> U-Boot> tftpboot 200000 v6.6/image.fit.nocomp
> Waiting for Ethernet connection... done.
> Using smsc95xx_eth device
> TFTP from server 192.168.1.10; our IP address is 192.168.1.100
> Filename 'v6.6/image.fit.nocomp'.
> Load address: 0x200000
> Loading: ##################################################  82 MiB
>           3.2 MiB/s
> done
> Bytes transferred = 85984256 (5200400 hex)
> U-Boot> U-Boot> crc32 200000 $filesize
> CRC32 for 00200000 ... 054003ff ==> 754c839a
> U-Boot> U-Boot> bootm 200000
> ## Loading kernel from FIT Image at 00200000 ...
> Could not find configuration node
> ERROR -2: can't get kernel image!
> U-Boot>
> 
> And in u_boot_boardenv_rpi_arm64.py:
> env__tftp_boot_test_skip = False
> 
> env__net_tftp_bootable_file = {
>      'fn': 'v6.6/image.fit.nocomp',
>      'addr': 0x00200000,
>      'size': 85984256,
>      'crc32': '754c839a',
>      'pattern': 'Linux',
>      'config': 'conf-852',
> }
> 
> But it's not trying to boot conf-852 but instead just passing the
> address. This image lacks a default config, which your example has and I
> think is why the tests work in your case.
> 

Hi,

Yes, this case expects to have some default config in fit image as it 
uses 'bootm <addr>' command to boot, below change in fit image should work.

configurations {
     default = "conf-852";

test_net_tftpboot_boot_config - This case will boot from the given 
config: 'bootm 200000#conf-852'

Regards,
Love Kumar
Tom Rini May 7, 2024, 1:20 p.m. UTC | #4
On Tue, May 07, 2024 at 11:22:45AM +0530, Love Kumar wrote:
> 
> 
> On 04/05/24 1:48 am, Tom Rini wrote:
> > On Fri, May 03, 2024 at 05:39:46PM +0530, Love Kumar wrote:
> > 
> > > Add tests for booting image using tftpboot/pxe boot commands, tftpboot
> > > boot case loads the FIT image into DDR and boots using bootm command
> > > whereas pxe boot cases downloads the pxe configuration file from the
> > > TFTP server and interprets it to boot the images mentioned in the pxe
> > > configurations file.
> > > This test relies on boardenv_* containing configuration values including
> > > the parameter 'pattern'. tftpboot/pxe boot cases boots the Linux till the
> > > boot log pattern value is matched. For example, if the parameter
> > > 'pattern' is defined as 'login:', it will boot till login prompt.
> > > 
> > > Signed-off-by: Love Kumar <love.kumar@amd.com>
> > 
> > I'm not quite sure where the problem is, next. After enabling FIT image
> > support in my build so I can use the image I have on hand:
> > U-Boot> tftpboot 200000 v6.6/image.fit.nocomp
> > Waiting for Ethernet connection... done.
> > Using smsc95xx_eth device
> > TFTP from server 192.168.1.10; our IP address is 192.168.1.100
> > Filename 'v6.6/image.fit.nocomp'.
> > Load address: 0x200000
> > Loading: ##################################################  82 MiB
> >           3.2 MiB/s
> > done
> > Bytes transferred = 85984256 (5200400 hex)
> > U-Boot> U-Boot> crc32 200000 $filesize
> > CRC32 for 00200000 ... 054003ff ==> 754c839a
> > U-Boot> U-Boot> bootm 200000
> > ## Loading kernel from FIT Image at 00200000 ...
> > Could not find configuration node
> > ERROR -2: can't get kernel image!
> > U-Boot>
> > 
> > And in u_boot_boardenv_rpi_arm64.py:
> > env__tftp_boot_test_skip = False
> > 
> > env__net_tftp_bootable_file = {
> >      'fn': 'v6.6/image.fit.nocomp',
> >      'addr': 0x00200000,
> >      'size': 85984256,
> >      'crc32': '754c839a',
> >      'pattern': 'Linux',
> >      'config': 'conf-852',
> > }
> > 
> > But it's not trying to boot conf-852 but instead just passing the
> > address. This image lacks a default config, which your example has and I
> > think is why the tests work in your case.
> > 
> 
> Hi,
> 
> Yes, this case expects to have some default config in fit image as it uses
> 'bootm <addr>' command to boot, below change in fit image should work.
> 
> configurations {
>     default = "conf-852";
> 
> test_net_tftpboot_boot_config - This case will boot from the given config:
> 'bootm 200000#conf-852'

I wasn't clear, sorry. The problem is that since we define the config to
use, which is good, we need to then use it. I intentionally have a FIT
image that supports every aarch64 platform and I'd rather use it for
every platform and not a per-platform FIT image.
Michal Simek May 7, 2024, 1:26 p.m. UTC | #5
Hi Tom,

út 7. 5. 2024 v 15:20 odesílatel Tom Rini <trini@konsulko.com> napsal:

> On Tue, May 07, 2024 at 11:22:45AM +0530, Love Kumar wrote:
> >
> >
> > On 04/05/24 1:48 am, Tom Rini wrote:
> > > On Fri, May 03, 2024 at 05:39:46PM +0530, Love Kumar wrote:
> > >
> > > > Add tests for booting image using tftpboot/pxe boot commands,
> tftpboot
> > > > boot case loads the FIT image into DDR and boots using bootm command
> > > > whereas pxe boot cases downloads the pxe configuration file from the
> > > > TFTP server and interprets it to boot the images mentioned in the pxe
> > > > configurations file.
> > > > This test relies on boardenv_* containing configuration values
> including
> > > > the parameter 'pattern'. tftpboot/pxe boot cases boots the Linux
> till the
> > > > boot log pattern value is matched. For example, if the parameter
> > > > 'pattern' is defined as 'login:', it will boot till login prompt.
> > > >
> > > > Signed-off-by: Love Kumar <love.kumar@amd.com>
> > >
> > > I'm not quite sure where the problem is, next. After enabling FIT image
> > > support in my build so I can use the image I have on hand:
> > > U-Boot> tftpboot 200000 v6.6/image.fit.nocomp
> > > Waiting for Ethernet connection... done.
> > > Using smsc95xx_eth device
> > > TFTP from server 192.168.1.10; our IP address is 192.168.1.100
> > > Filename 'v6.6/image.fit.nocomp'.
> > > Load address: 0x200000
> > > Loading: ##################################################  82 MiB
> > >           3.2 MiB/s
> > > done
> > > Bytes transferred = 85984256 (5200400 hex)
> > > U-Boot> U-Boot> crc32 200000 $filesize
> > > CRC32 for 00200000 ... 054003ff ==> 754c839a
> > > U-Boot> U-Boot> bootm 200000
> > > ## Loading kernel from FIT Image at 00200000 ...
> > > Could not find configuration node
> > > ERROR -2: can't get kernel image!
> > > U-Boot>
> > >
> > > And in u_boot_boardenv_rpi_arm64.py:
> > > env__tftp_boot_test_skip = False
> > >
> > > env__net_tftp_bootable_file = {
> > >      'fn': 'v6.6/image.fit.nocomp',
> > >      'addr': 0x00200000,
> > >      'size': 85984256,
> > >      'crc32': '754c839a',
> > >      'pattern': 'Linux',
> > >      'config': 'conf-852',
> > > }
> > >
> > > But it's not trying to boot conf-852 but instead just passing the
> > > address. This image lacks a default config, which your example has and
> I
> > > think is why the tests work in your case.
> > >
> >
> > Hi,
> >
> > Yes, this case expects to have some default config in fit image as it
> uses
> > 'bootm <addr>' command to boot, below change in fit image should work.
> >
> > configurations {
> >     default = "conf-852";
> >
> > test_net_tftpboot_boot_config - This case will boot from the given
> config:
> > 'bootm 200000#conf-852'
>
> I wasn't clear, sorry. The problem is that since we define the config to
> use, which is good, we need to then use it. I intentionally have a FIT
> image that supports every aarch64 platform and I'd rather use it for
> every platform and not a per-platform FIT image.
>

What about putting those two tests together? I mean if config is not
defined used default configuration,
if config is defined use it.

Thanks,
Michal
Tom Rini May 7, 2024, 1:26 p.m. UTC | #6
On Tue, May 07, 2024 at 11:22:45AM +0530, Love Kumar wrote:
> 
> 
> On 04/05/24 1:48 am, Tom Rini wrote:
> > On Fri, May 03, 2024 at 05:39:46PM +0530, Love Kumar wrote:
> > 
> > > Add tests for booting image using tftpboot/pxe boot commands, tftpboot
> > > boot case loads the FIT image into DDR and boots using bootm command
> > > whereas pxe boot cases downloads the pxe configuration file from the
> > > TFTP server and interprets it to boot the images mentioned in the pxe
> > > configurations file.
> > > This test relies on boardenv_* containing configuration values including
> > > the parameter 'pattern'. tftpboot/pxe boot cases boots the Linux till the
> > > boot log pattern value is matched. For example, if the parameter
> > > 'pattern' is defined as 'login:', it will boot till login prompt.
> > > 
> > > Signed-off-by: Love Kumar <love.kumar@amd.com>
> > 
> > I'm not quite sure where the problem is, next. After enabling FIT image
> > support in my build so I can use the image I have on hand:
> > U-Boot> tftpboot 200000 v6.6/image.fit.nocomp
> > Waiting for Ethernet connection... done.
> > Using smsc95xx_eth device
> > TFTP from server 192.168.1.10; our IP address is 192.168.1.100
> > Filename 'v6.6/image.fit.nocomp'.
> > Load address: 0x200000
> > Loading: ##################################################  82 MiB
> >           3.2 MiB/s
> > done
> > Bytes transferred = 85984256 (5200400 hex)
> > U-Boot> U-Boot> crc32 200000 $filesize
> > CRC32 for 00200000 ... 054003ff ==> 754c839a
> > U-Boot> U-Boot> bootm 200000
> > ## Loading kernel from FIT Image at 00200000 ...
> > Could not find configuration node
> > ERROR -2: can't get kernel image!
> > U-Boot>
> > 
> > And in u_boot_boardenv_rpi_arm64.py:
> > env__tftp_boot_test_skip = False
> > 
> > env__net_tftp_bootable_file = {
> >      'fn': 'v6.6/image.fit.nocomp',
> >      'addr': 0x00200000,
> >      'size': 85984256,
> >      'crc32': '754c839a',
> >      'pattern': 'Linux',
> >      'config': 'conf-852',
> > }
> > 
> > But it's not trying to boot conf-852 but instead just passing the
> > address. This image lacks a default config, which your example has and I
> > think is why the tests work in your case.
> > 
> 
> Hi,
> 
> Yes, this case expects to have some default config in fit image as it uses
> 'bootm <addr>' command to boot, below change in fit image should work.
> 
> configurations {
>     default = "conf-852";
> 
> test_net_tftpboot_boot_config - This case will boot from the given config:
> 'bootm 200000#conf-852'

I think perhaps a related issue is that you're wanting to test that a
FIT image with a default config works as expected. This should be added
to test/py/tests/test_fit.py where we already construct and test
assorted cases like that, and not handled in the "test OS boot" test I
believe.
Tom Rini May 7, 2024, 2:35 p.m. UTC | #7
On Tue, May 07, 2024 at 03:26:18PM +0200, Michal Simek wrote:
> Hi Tom,
> 
> út 7. 5. 2024 v 15:20 odesílatel Tom Rini <trini@konsulko.com> napsal:
> 
> > On Tue, May 07, 2024 at 11:22:45AM +0530, Love Kumar wrote:
> > >
> > >
> > > On 04/05/24 1:48 am, Tom Rini wrote:
> > > > On Fri, May 03, 2024 at 05:39:46PM +0530, Love Kumar wrote:
> > > >
> > > > > Add tests for booting image using tftpboot/pxe boot commands,
> > tftpboot
> > > > > boot case loads the FIT image into DDR and boots using bootm command
> > > > > whereas pxe boot cases downloads the pxe configuration file from the
> > > > > TFTP server and interprets it to boot the images mentioned in the pxe
> > > > > configurations file.
> > > > > This test relies on boardenv_* containing configuration values
> > including
> > > > > the parameter 'pattern'. tftpboot/pxe boot cases boots the Linux
> > till the
> > > > > boot log pattern value is matched. For example, if the parameter
> > > > > 'pattern' is defined as 'login:', it will boot till login prompt.
> > > > >
> > > > > Signed-off-by: Love Kumar <love.kumar@amd.com>
> > > >
> > > > I'm not quite sure where the problem is, next. After enabling FIT image
> > > > support in my build so I can use the image I have on hand:
> > > > U-Boot> tftpboot 200000 v6.6/image.fit.nocomp
> > > > Waiting for Ethernet connection... done.
> > > > Using smsc95xx_eth device
> > > > TFTP from server 192.168.1.10; our IP address is 192.168.1.100
> > > > Filename 'v6.6/image.fit.nocomp'.
> > > > Load address: 0x200000
> > > > Loading: ##################################################  82 MiB
> > > >           3.2 MiB/s
> > > > done
> > > > Bytes transferred = 85984256 (5200400 hex)
> > > > U-Boot> U-Boot> crc32 200000 $filesize
> > > > CRC32 for 00200000 ... 054003ff ==> 754c839a
> > > > U-Boot> U-Boot> bootm 200000
> > > > ## Loading kernel from FIT Image at 00200000 ...
> > > > Could not find configuration node
> > > > ERROR -2: can't get kernel image!
> > > > U-Boot>
> > > >
> > > > And in u_boot_boardenv_rpi_arm64.py:
> > > > env__tftp_boot_test_skip = False
> > > >
> > > > env__net_tftp_bootable_file = {
> > > >      'fn': 'v6.6/image.fit.nocomp',
> > > >      'addr': 0x00200000,
> > > >      'size': 85984256,
> > > >      'crc32': '754c839a',
> > > >      'pattern': 'Linux',
> > > >      'config': 'conf-852',
> > > > }
> > > >
> > > > But it's not trying to boot conf-852 but instead just passing the
> > > > address. This image lacks a default config, which your example has and
> > I
> > > > think is why the tests work in your case.
> > > >
> > >
> > > Hi,
> > >
> > > Yes, this case expects to have some default config in fit image as it
> > uses
> > > 'bootm <addr>' command to boot, below change in fit image should work.
> > >
> > > configurations {
> > >     default = "conf-852";
> > >
> > > test_net_tftpboot_boot_config - This case will boot from the given
> > config:
> > > 'bootm 200000#conf-852'
> >
> > I wasn't clear, sorry. The problem is that since we define the config to
> > use, which is good, we need to then use it. I intentionally have a FIT
> > image that supports every aarch64 platform and I'd rather use it for
> > every platform and not a per-platform FIT image.
> >
> 
> What about putting those two tests together? I mean if config is not
> defined used default configuration,
> if config is defined use it.

So, I followed up with another email too about tests for FIT vs tests
for OS boot. If we update the exiting FIT tests to test that the default
config is used if present would that be a better way to cover the intent
here?
diff mbox series

Patch

diff --git a/test/py/tests/test_net_boot.py b/test/py/tests/test_net_boot.py
new file mode 100644
index 000000000000..fb0fb7e80414
--- /dev/null
+++ b/test/py/tests/test_net_boot.py
@@ -0,0 +1,394 @@ 
+# SPDX-License-Identifier: GPL-2.0
+# (C) Copyright 2023, Advanced Micro Devices, Inc.
+
+import pytest
+import u_boot_utils
+import test_net
+
+"""
+Note: This test relies on boardenv_* containing configuration values to define
+which the network environment available for testing. Without this, this test
+will be automatically skipped.
+
+For example:
+
+# Details regarding a boot image file that may be read from a TFTP server. This
+# variable may be omitted or set to None if TFTP boot testing is not possible
+# or desired.
+env__net_tftp_bootable_file = {
+    'fn': 'image.ub',
+    'addr': 0x10000000,
+    'size': 5058624,
+    'crc32': 'c2244b26',
+    'pattern': 'Linux',
+    'config': 'config@2',
+    'timeout': 50000,
+}
+
+# False or omitted if a TFTP boot test should be tested.
+# If TFTP boot testing is not possible or desired, set this variable to True.
+# For example: If FIT image is not proper to boot
+env__tftp_boot_test_skip = False
+
+# Here is the example of FIT image configurations:
+configurations {
+    default = "config@1";
+    config@1 {
+        description = "Boot Linux kernel with config@1";
+        kernel = "kernel@0";
+        fdt = "fdt@0";
+        ramdisk = "ramdisk@0";
+        hash@1 {
+            algo = "sha1";
+        };
+    };
+    config@2 {
+        description = "Boot Linux kernel with config@2";
+        kernel = "kernel@1";
+        fdt = "fdt@1";
+        ramdisk = "ramdisk@1";
+        hash@1 {
+            algo = "sha1";
+        };
+    };
+};
+
+# Details regarding a file that may be read from a TFTP server. This variable
+# may be omitted or set to None if PXE testing is not possible or desired.
+env__net_pxe_bootable_file = {
+    'fn': 'default',
+    'addr': 0x10000000,
+    'size': 74,
+    'timeout': 50000,
+    'pattern': 'Linux',
+    'valid_label': '1',
+    'invalid_label': '2',
+    'exp_str_invalid': 'Skipping install for failure retrieving',
+    'local_label': '3',
+    'exp_str_local': 'missing environment variable: localcmd',
+    'empty_label': '4',
+    'exp_str_empty': 'No kernel given, skipping boot',
+}
+
+# False or omitted if a PXE boot test should be tested.
+# If PXE boot testing is not possible or desired, set this variable to True.
+# For example: If pxe configuration file is not proper to boot
+env__pxe_boot_test_skip = False
+
+# Here is the example of pxe configuration file ordered based on the execution
+# flow:
+1) /tftpboot/pxelinux.cfg/default-arm-zynqmp
+
+    menu include pxelinux.cfg/default-arm
+    timeout 50
+
+    default Linux
+
+2) /tftpboot/pxelinux.cfg/default-arm
+
+    menu title Linux boot selections
+    menu include pxelinux.cfg/default
+
+    label install
+        menu label Invalid boot
+        kernel kernels/install.bin
+        append console=ttyAMA0,38400 debug earlyprintk
+        initrd initrds/uzInitrdDebInstall
+
+    label local
+        menu label Local boot
+        append root=/dev/sdb1
+        localboot 1
+
+    label boot
+        menu label Empty boot
+
+3) /tftpboot/pxelinux.cfg/default
+
+    label Linux
+        menu label Boot kernel
+        kernel Image
+        fdt system.dtb
+        initrd rootfs.cpio.gz.u-boot
+"""
+
+def setup_tftpboot_boot(u_boot_console):
+    f = u_boot_console.config.env.get('env__net_tftp_bootable_file', None)
+    if not f:
+        pytest.skip('No TFTP bootable file to read')
+
+    test_net.test_net_dhcp(u_boot_console)
+    if not test_net.net_set_up:
+        test_net.test_net_setup_static(u_boot_console)
+
+    addr = f.get('addr', None)
+    if not addr:
+        addr = u_boot_utils.find_ram_base(u_boot_console)
+
+    fn = f['fn']
+    timeout = f.get('timeout', 50000)
+
+    with u_boot_console.temporary_timeout(timeout):
+        output = u_boot_console.run_command('tftpboot %x %s' % (addr, fn))
+
+    expected_text = 'Bytes transferred = '
+    sz = f.get('size', None)
+    if sz:
+        expected_text += '%d' % sz
+    assert expected_text in output
+
+    expected_crc = f.get('crc32', None)
+    output = u_boot_console.run_command('crc32 %x $filesize' % addr)
+    if expected_crc:
+        assert expected_crc in output
+
+    pattern = f.get('pattern')
+    config = f.get('config', None)
+
+    return addr, pattern, timeout, config
+
+@pytest.mark.buildconfigspec('cmd_net')
+def test_net_tftpboot_boot(u_boot_console):
+    """Boot the loaded image
+
+    A boot file (fit image) is downloaded from the TFTP server and booted using
+    bootm command with the default fit configuration, its boot log pattern are
+    validated.
+
+    The details of the file to download are provided by the boardenv_* file;
+    see the comment at the beginning of this file.
+    """
+    if u_boot_console.config.env.get('env__tftp_boot_test_skip', True):
+        pytest.skip('TFTP boot test is not enabled!')
+
+    addr, pattern, timeout, imcfg = setup_tftpboot_boot(u_boot_console)
+    with u_boot_console.temporary_timeout(timeout):
+        try:
+            # wait_for_prompt=False makes the core code not wait for the U-Boot
+            # prompt code to be seen, since it won't be on a successful kernel
+            # boot
+            u_boot_console.run_command('bootm %x'% addr, wait_for_prompt=False)
+            # You might want to expand wait_for() with options to add extra bad
+            # patterns which immediately indicate a failed boot, or add a new
+            # "with object" function u_boot_console.enable_check() that can
+            # cause extra patterns like the U-Boot console prompt, U-Boot boot
+            # error messages, kernel boot error messages, etc. to fail the
+            # wait_for().
+
+            # Wait for boot log pattern
+            u_boot_console.wait_for(pattern)
+        finally:
+            # This forces the console object to be shutdown, so any subsequent
+            # test will reset the board back into U-Boot. We want to force this
+            # no matter whether the kernel boot passed or failed.
+            u_boot_console.drain_console()
+            u_boot_console.cleanup_spawn()
+
+@pytest.mark.buildconfigspec('cmd_net')
+def test_net_tftpboot_boot_config(u_boot_console):
+    """Boot the loaded image from FIT image configuration
+
+    A boot file (fit image) is downloaded from the TFTP server and booted using
+    bootm command with the custom fit configuration, its boot log pattern are
+    validated.
+
+    The details of the file to download are provided by the boardenv_* file;
+    see the comment at the beginning of this file.
+    """
+    if u_boot_console.config.env.get('env__tftp_boot_test_skip', True):
+        pytest.skip('TFTP boot test is not enabled!')
+
+    addr, pattern, timeout, imcfg = setup_tftpboot_boot(u_boot_console)
+
+    with u_boot_console.temporary_timeout(timeout):
+        try:
+            u_boot_console.run_command(
+                'bootm %x#%s' % (addr, imcfg), wait_for_prompt=False
+            )
+            u_boot_console.wait_for(pattern)
+        finally:
+            u_boot_console.drain_console()
+            u_boot_console.cleanup_spawn()
+
+def setup_pxe_boot(u_boot_console):
+    f = u_boot_console.config.env.get('env__net_pxe_bootable_file', None)
+    if not f:
+        pytest.skip('No PXE bootable file to read')
+
+    test_net.test_net_dhcp(u_boot_console)
+    test_net.test_net_setup_static(u_boot_console)
+    return f
+
+@pytest.mark.buildconfigspec('cmd_net')
+@pytest.mark.buildconfigspec('cmd_pxe')
+def test_net_pxe_boot(u_boot_console):
+    """Test the pxe boot command.
+
+    A pxe configuration file is downloaded from the TFTP server and interpreted
+    to boot the images mentioned in pxe configuration file.
+
+    The details of the file to download are provided by the boardenv_* file;
+    see the comment at the beginning of this file.
+    """
+    if u_boot_console.config.env.get('env__pxe_boot_test_skip', True):
+        pytest.skip('PXE boot test is not enabled!')
+
+    f = setup_pxe_boot(u_boot_console)
+    addr = f.get('addr', None)
+    timeout = f.get('timeout', u_boot_console.p.timeout)
+    fn = f['fn']
+
+    with u_boot_console.temporary_timeout(timeout):
+        output = u_boot_console.run_command('pxe get')
+
+    expected_text = 'Bytes transferred = '
+    sz = f.get('size', None)
+    if sz:
+        expected_text += '%d' % sz
+    assert 'TIMEOUT' not in output
+    assert expected_text in output
+    assert "Config file 'default.boot' found" in output
+
+    pattern = f.get('pattern')
+    if not addr:
+        pxe_boot_cmd = 'pxe boot'
+    else:
+        pxe_boot_cmd = 'pxe boot %x' % addr
+
+    with u_boot_console.temporary_timeout(timeout):
+        try:
+            u_boot_console.run_command(pxe_boot_cmd, wait_for_prompt=False)
+            u_boot_console.wait_for(pattern)
+        finally:
+            u_boot_console.drain_console()
+            u_boot_console.cleanup_spawn()
+
+@pytest.mark.buildconfigspec('cmd_net')
+@pytest.mark.buildconfigspec('cmd_pxe')
+def test_net_pxe_boot_config(u_boot_console):
+    """Test the pxe boot command by selecting different combination of labels
+
+    A pxe configuration file is downloaded from the TFTP server and interpreted
+    to boot the images mentioned in pxe configuration file.
+
+    The details of the file to download are provided by the boardenv_* file;
+    see the comment at the beginning of this file.
+    """
+    if u_boot_console.config.env.get('env__pxe_boot_test_skip', True):
+        pytest.skip('PXE boot test is not enabled!')
+
+    f = setup_pxe_boot(u_boot_console)
+    addr = f.get('addr', None)
+    timeout = f.get('timeout', u_boot_console.p.timeout)
+    fn = f['fn']
+    local_label = f['local_label']
+    empty_label = f['empty_label']
+    exp_str_local = f['exp_str_local']
+    exp_str_empty = f['exp_str_empty']
+
+    with u_boot_console.temporary_timeout(timeout):
+        output = u_boot_console.run_command('pxe get')
+
+    expected_text = 'Bytes transferred = '
+    sz = f.get('size', None)
+    if sz:
+        expected_text += '%d' % sz
+    assert 'TIMEOUT' not in output
+    assert expected_text in output
+    assert "Config file 'default.boot' found" in output
+
+    pattern = f.get('pattern')
+    if not addr:
+        pxe_boot_cmd = 'pxe boot'
+    else:
+        pxe_boot_cmd = 'pxe boot %x' % addr
+
+    with u_boot_console.temporary_timeout(timeout):
+        try:
+            u_boot_console.run_command(pxe_boot_cmd, wait_for_prompt=False)
+
+            # pxe config is loaded where multiple labels are there and need to
+            # select particular label to boot and check for expected string
+            # In this case, local label is selected and it should look for
+            # localcmd env variable and if that variable is not defined it
+            # should not boot it and come out to u-boot prompt
+            u_boot_console.wait_for('Enter choice:')
+            u_boot_console.run_command(local_label, wait_for_prompt=False)
+            expected_str = u_boot_console.p.expect([exp_str_local])
+            assert (
+                expected_str == 0
+            ), f'Expected string: {exp_str_local} did not match!'
+
+            # In this case, empty label is selected and it should look for
+            # kernel image path and if it is not set it should fail it and load
+            # default label to boot
+            u_boot_console.run_command(pxe_boot_cmd, wait_for_prompt=False)
+            u_boot_console.wait_for('Enter choice:')
+            u_boot_console.run_command(empty_label, wait_for_prompt=False)
+            expected_str = u_boot_console.p.expect([exp_str_empty])
+            assert (
+                expected_str == 0
+            ), f'Expected string: {exp_str_empty} did not match!'
+
+            u_boot_console.wait_for(pattern)
+        finally:
+            u_boot_console.drain_console()
+            u_boot_console.cleanup_spawn()
+
+@pytest.mark.buildconfigspec('cmd_net')
+@pytest.mark.buildconfigspec('cmd_pxe')
+def test_net_pxe_boot_config_invalid(u_boot_console):
+    """Test the pxe boot command by selecting invalid label
+
+    A pxe configuration file is downloaded from the TFTP server and interpreted
+    to boot the images mentioned in pxe configuration file.
+
+    The details of the file to download are provided by the boardenv_* file;
+    see the comment at the beginning of this file.
+    """
+    if u_boot_console.config.env.get('env__pxe_boot_test_skip', True):
+        pytest.skip('PXE boot test is not enabled!')
+
+    f = setup_pxe_boot(u_boot_console)
+    addr = f.get('addr', None)
+    timeout = f.get('timeout', u_boot_console.p.timeout)
+    fn = f['fn']
+    invalid_label = f['invalid_label']
+    exp_str_invalid = f['exp_str_invalid']
+
+    with u_boot_console.temporary_timeout(timeout):
+        output = u_boot_console.run_command('pxe get')
+
+    expected_text = 'Bytes transferred = '
+    sz = f.get('size', None)
+    if sz:
+        expected_text += '%d' % sz
+    assert 'TIMEOUT' not in output
+    assert expected_text in output
+    assert "Config file 'default.boot' found" in output
+
+    pattern = f.get('pattern')
+    if not addr:
+        pxe_boot_cmd = 'pxe boot'
+    else:
+        pxe_boot_cmd = 'pxe boot %x' % addr
+
+    with u_boot_console.temporary_timeout(timeout):
+        try:
+            u_boot_console.run_command(pxe_boot_cmd, wait_for_prompt=False)
+
+            # pxe config is loaded where multiple labels are there and need to
+            # select particular label to boot and check for expected string
+            # In this case invalid label is selected, it should load invalid
+            # label and if it fails it should load the default label to boot
+            u_boot_console.wait_for('Enter choice:')
+            u_boot_console.run_command(invalid_label, wait_for_prompt=False)
+            expected_str = u_boot_console.p.expect([exp_str_invalid])
+            assert (
+                expected_str == 0
+            ), f'Expected string: {exp_str_invalid} did not match!'
+
+            u_boot_console.wait_for(pattern)
+        finally:
+            u_boot_console.drain_console()
+            u_boot_console.cleanup_spawn()