Running Rust tests for UEFI


 

Hello everyone, the project has now reached the stage where it is
possible to build for UEFI just like an std supporting Rust target.
However, running tests is where it gets a bit tricky:

While there are some rust targets that run on QEMU emulation for
testing [1] (as opposed to just docker), this is currently achieved by
2 tools: remote-test-client [2] and remote-test-server [3] which are
programs for sending test programs and libraries to the emulator, and
running the tests within the emulator, and reading the results.

This means that the rust-test-server [3] needs to run in the UEFI
environment. This means it needs the `sys::net` module implemented. As
suggested in the last meeting, I was using a dummy implementation of
net. However, for using the current Rust testing environment, we
simply need to implement net.

There is also the alternative of using stdio in qemu for testing, but
that will mean significant reworking of the Rust testing framework
(which seems to be more difficult than implementing `net`)

So I think that it would be better to implement the `net` module
first. The primitives that need to be implemented in this module are
TcpSocket, TcpListener, and UdpSocket (unsupported version link [4]).

So should I go ahead with implementing `net`? Is there anything
special that I should consider?

Yours Sincerely,
Ayush Singh

[1]: https://rustc-dev-guide.rust-lang.org/tests/running.html#testing-on-emulators
[2]: https://github.com/rust-lang/rust/tree/master/src/tools/remote-test-client
[3]: https://github.com/rust-lang/rust/tree/master/src/tools/remote-test-server
[4]: https://github.com/rust-lang/rust/blob/5b9775fe17893cba641a071de7e0a7c8f478c41b/library/std/src/sys/unsupported/net.rs


 

After some more research, I have found 2 main ways of implementing net:

1. Use the TCP and UDP protocols defined in UEFI spec. They seem
pretty easy to use. But while they are an official protocol, the
availability is shoddy (r-efi does not define either of them). Still
should work well enough if testing is the main reason for implementing
them.

2. Use Simple Network Protocol (SNP). This is a very basic protocol
that basically allows transmitting and receiving packets. Availability
is pretty good, but implementing TCP and UDP using it will require a
lot of work.

So I wanted to ask about the availability of TCP and UDP protocols vs
SNP? If the TCP and UDP protocols are likely to be available in
presence of SNP, then well, I will directly use those.

Also, how should I handle when multiple Handles are returned by
`LocateHandle`? One option can be to use the 1st handle by default but
provide functions under `std::os` to allow users to use a particular
handle if they want (although this will mean caching the Handle).

Since all the functions in net return `Result` we can just return an
error if the device does not have networking support.

Ayush Singh

On Sat, Jul 2, 2022 at 1:05 AM Ayush Singh via groups.io
<ayushdevel1325@...> wrote:

Hello everyone, the project has now reached the stage where it is
possible to build for UEFI just like an std supporting Rust target.
However, running tests is where it gets a bit tricky:

While there are some rust targets that run on QEMU emulation for
testing [1] (as opposed to just docker), this is currently achieved by
2 tools: remote-test-client [2] and remote-test-server [3] which are
programs for sending test programs and libraries to the emulator, and
running the tests within the emulator, and reading the results.

This means that the rust-test-server [3] needs to run in the UEFI
environment. This means it needs the `sys::net` module implemented. As
suggested in the last meeting, I was using a dummy implementation of
net. However, for using the current Rust testing environment, we
simply need to implement net.

There is also the alternative of using stdio in qemu for testing, but
that will mean significant reworking of the Rust testing framework
(which seems to be more difficult than implementing `net`)

So I think that it would be better to implement the `net` module
first. The primitives that need to be implemented in this module are
TcpSocket, TcpListener, and UdpSocket (unsupported version link [4]).

So should I go ahead with implementing `net`? Is there anything
special that I should consider?

Yours Sincerely,
Ayush Singh

[1]: https://rustc-dev-guide.rust-lang.org/tests/running.html#testing-on-emulators
[2]: https://github.com/rust-lang/rust/tree/master/src/tools/remote-test-client
[3]: https://github.com/rust-lang/rust/tree/master/src/tools/remote-test-server
[4]: https://github.com/rust-lang/rust/blob/5b9775fe17893cba641a071de7e0a7c8f478c41b/library/std/src/sys/unsupported/net.rs





Pedro Falcato
 

Hi,

Here's my 2 cents: don't worry too much about tests, if that will slow you down considerably. You should focus on getting a usable runtime environment first, tests should be a secondary thing on your mind (we don't have many tests in EDK2 anyway, despite some ongoing efforts).

On Sat, Jul 2, 2022 at 1:23 PM Ayush Singh <ayushdevel1325@...> wrote:
After some more research, I have found 2 main ways of implementing net:

1. Use the TCP and UDP protocols defined in UEFI spec. They seem
pretty easy to use. But while they are an official protocol, the
availability is shoddy (r-efi does not define either of them). Still
should work well enough if testing is the main reason for implementing
them.

2. Use Simple Network Protocol (SNP). This is a very basic protocol
that basically allows transmitting and receiving packets. Availability
is pretty good, but implementing TCP and UDP using it will require a
lot of work.

So I wanted to ask about the availability of TCP and UDP protocols vs
SNP? If the TCP and UDP protocols are likely to be available in
presence of SNP, then well, I will directly use those.
I don't know about their availability, but I would consider only supporting tests on firmware which has the TCP and UDP protocols; re-implementing TCP is totally non-trivial.

Also, how should I handle when multiple Handles are returned by
`LocateHandle`? One option can be to use the 1st handle by default but
provide functions under `std::os` to allow users to use a particular
handle if they want (although this will mean caching the Handle).

I'm not big into Rust but isn't there a way to just pass a reference into an array into a function? You'd essentially just do that.
Since all the functions in net return `Result` we can just return an
error if the device does not have networking support.

Ayush Singh

On Sat, Jul 2, 2022 at 1:05 AM Ayush Singh via groups.io
<ayushdevel1325=gmail.com@groups.io> wrote:
>
> Hello everyone, the project has now reached the stage where it is
> possible to build for UEFI just like an std supporting Rust target.
> However, running tests is where it gets a bit tricky:
>
> While there are some rust targets that run on QEMU emulation for
> testing [1] (as opposed to just docker), this is currently achieved by
> 2 tools: remote-test-client [2] and remote-test-server [3] which are
> programs for sending test programs and libraries to the emulator, and
> running the tests within the emulator, and reading the results.
>
> This means that the rust-test-server [3] needs to run in the UEFI
> environment. This means it needs the `sys::net` module implemented. As
> suggested in the last meeting, I was using a dummy implementation of
> net. However, for using the current Rust testing environment, we
> simply need to implement net.
>
> There is also the alternative of using stdio in qemu for testing, but
> that will mean significant reworking of the Rust testing framework
> (which seems to be more difficult than implementing `net`)
>
> So I think that it would be better to implement the `net` module
> first. The primitives that need to be implemented in this module are
> TcpSocket, TcpListener, and UdpSocket (unsupported version link [4]).
>
> So should I go ahead with implementing `net`? Is there anything
> special that I should consider?
>
> Yours Sincerely,
> Ayush Singh
>
> [1]: https://rustc-dev-guide.rust-lang.org/tests/running.html#testing-on-emulators
> [2]: https://github.com/rust-lang/rust/tree/master/src/tools/remote-test-client
> [3]: https://github.com/rust-lang/rust/tree/master/src/tools/remote-test-server
> [4]: https://github.com/rust-lang/rust/blob/5b9775fe17893cba641a071de7e0a7c8f478c41b/library/std/src/sys/unsupported/net.rs
>
>
>
>
>







--
Pedro Falcato


 

Here's my 2 cents: don't worry too much about tests, if that will slow you down considerably. You should focus on getting a usable runtime environment first, tests should be a secondary thing on your mind (we don't have many tests in EDK2 anyway, despite some ongoing efforts).
Well, I have implemented enough std to make it possible to build for
UEFI like the official Rust targets. There are around 13,000 tests in
the Rust CI that are platform agnostic and are run for all Tier 1 and
Tier 2 targets with std support. Since the final goal is to get the
UEFI std upstreamed, it kinda needs to be able to run these tests.

I don't know about their availability, but I would consider only supporting tests on firmware which has the TCP and UDP protocols; re-implementing TCP is totally non-trivial.
Ok, that sounds good to me.

I'm not big into Rust but isn't there a way to just pass a reference into an array into a function? You'd essentially just do that.
I think you might have misunderstood a bit. In the current
implementation of net stuff in Rust, basically, the platform seems to
handle selecting the device and all. However, in UEFI, the
`LocateHanldle` returns an array of all the devices that implement the
protocol. So well, the internal implementation will need to select
which device to connect to. Basically, it is not possible to change
the signatures of any of the net stuff (to take the handle as input)
just for UEFI.

Ayush Singh

On Sun, Jul 3, 2022 at 1:18 AM Pedro Falcato <pedro.falcato@...> wrote:

Hi,

Here's my 2 cents: don't worry too much about tests, if that will slow you down considerably. You should focus on getting a usable runtime environment first, tests should be a secondary thing on your mind (we don't have many tests in EDK2 anyway, despite some ongoing efforts).

On Sat, Jul 2, 2022 at 1:23 PM Ayush Singh <ayushdevel1325@...> wrote:

After some more research, I have found 2 main ways of implementing net:

1. Use the TCP and UDP protocols defined in UEFI spec. They seem
pretty easy to use. But while they are an official protocol, the
availability is shoddy (r-efi does not define either of them). Still
should work well enough if testing is the main reason for implementing
them.

2. Use Simple Network Protocol (SNP). This is a very basic protocol
that basically allows transmitting and receiving packets. Availability
is pretty good, but implementing TCP and UDP using it will require a
lot of work.

So I wanted to ask about the availability of TCP and UDP protocols vs
SNP? If the TCP and UDP protocols are likely to be available in
presence of SNP, then well, I will directly use those.
I don't know about their availability, but I would consider only supporting tests on firmware which has the TCP and UDP protocols; re-implementing TCP is totally non-trivial.


Also, how should I handle when multiple Handles are returned by
`LocateHandle`? One option can be to use the 1st handle by default but
provide functions under `std::os` to allow users to use a particular
handle if they want (although this will mean caching the Handle).
I'm not big into Rust but isn't there a way to just pass a reference into an array into a function? You'd essentially just do that.

Since all the functions in net return `Result` we can just return an
error if the device does not have networking support.

Ayush Singh

On Sat, Jul 2, 2022 at 1:05 AM Ayush Singh via groups.io
<ayushdevel1325@...> wrote:

Hello everyone, the project has now reached the stage where it is
possible to build for UEFI just like an std supporting Rust target.
However, running tests is where it gets a bit tricky:

While there are some rust targets that run on QEMU emulation for
testing [1] (as opposed to just docker), this is currently achieved by
2 tools: remote-test-client [2] and remote-test-server [3] which are
programs for sending test programs and libraries to the emulator, and
running the tests within the emulator, and reading the results.

This means that the rust-test-server [3] needs to run in the UEFI
environment. This means it needs the `sys::net` module implemented. As
suggested in the last meeting, I was using a dummy implementation of
net. However, for using the current Rust testing environment, we
simply need to implement net.

There is also the alternative of using stdio in qemu for testing, but
that will mean significant reworking of the Rust testing framework
(which seems to be more difficult than implementing `net`)

So I think that it would be better to implement the `net` module
first. The primitives that need to be implemented in this module are
TcpSocket, TcpListener, and UdpSocket (unsupported version link [4]).

So should I go ahead with implementing `net`? Is there anything
special that I should consider?

Yours Sincerely,
Ayush Singh

[1]: https://rustc-dev-guide.rust-lang.org/tests/running.html#testing-on-emulators
[2]: https://github.com/rust-lang/rust/tree/master/src/tools/remote-test-client
[3]: https://github.com/rust-lang/rust/tree/master/src/tools/remote-test-server
[4]: https://github.com/rust-lang/rust/blob/5b9775fe17893cba641a071de7e0a7c8f478c41b/library/std/src/sys/unsupported/net.rs








--
Pedro Falcato