Skip to content

Commit 9bd0cdf

Browse files
author
T. Andrew Davis
committed
Refactor network state machine and implement GPT preparation and manifest writing
- Updated `InitState` to transition to `GptPrepState` instead of `DhcpState`. - Added `GptPrepState` for handling GPT partition creation and verification of disk space. - Introduced `LinkWaitState` to manage PHY link establishment before DHCP. - Created `ManifestState` for writing ISO manifest after download, supporting FAT32 and raw sector modes. - Added `TimeoutConfig` struct for managing timeouts based on TSC frequency. - Implemented standalone functions for manifest regeneration and writing. - Documented driver reset contract to ensure proper initialization and state management.
1 parent 1525a4d commit 9bd0cdf

27 files changed

Lines changed: 1849 additions & 3670 deletions

core/src/net/error.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ pub enum NetInitError {
3030
InvalidConfig,
3131
/// Operation timed out.
3232
Timeout,
33-
/// API is deprecated - use post-EBS bare_metal_main() instead.
33+
/// API is deprecated - use post-EBS download_with_config() instead.
3434
Deprecated,
3535
}
3636

@@ -50,7 +50,7 @@ impl NetInitError {
5050
Self::StackInit => "Network stack initialization failed",
5151
Self::InvalidConfig => "Invalid network configuration",
5252
Self::Timeout => "Operation timed out",
53-
Self::Deprecated => "API deprecated - use post-EBS bare_metal_main()",
53+
Self::Deprecated => "API deprecated - use post-EBS download_with_config()",
5454
}
5555
}
5656
}

core/src/net/init.rs

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,18 @@
33
//! # DEPRECATED
44
//!
55
//! This module is deprecated. Network initialization now happens **post-ExitBootServices**
6-
//! using the bare-metal network stack directly in `morpheus_network::mainloop::bare_metal_main`.
6+
//! using the modular state machine in `morpheus_network::mainloop::orchestrator`.
77
//!
88
//! The old flow (this module):
99
//! 1. Initialize in UEFI environment
1010
//! 2. Use factory pattern to detect/create devices
1111
//!
1212
//! The new flow:
13-
//! 1. Bootstrap displays menu, user selects ISO
13+
//! 1. hwinit normalizes hardware (bus mastering, DMA policy, etc)
1414
//! 2. ExitBootServices is called
15-
//! 3. Bare-metal stack initializes VirtIO directly
16-
//! 4. HTTP download proceeds
15+
//! 3. Network crate initializes its own drivers
16+
//! 4. `download_with_config()` runs the state machine
17+
//! 5. State flow: Init → GptPrep → LinkWait → DHCP → DNS → Connect → HTTP → Manifest → Done
1718
//!
1819
//! This stub is kept for API compatibility with existing imports.
1920
@@ -26,7 +27,7 @@ use super::status::NetworkStatus;
2627
///
2728
/// This type is kept for API compatibility but `NetworkInit::initialize()`
2829
/// always returns an error directing callers to use post-EBS flow.
29-
#[deprecated(note = "Network init moved to post-EBS. Use bare_metal_main() instead.")]
30+
#[deprecated(note = "Network init moved to post-EBS. Use download_with_config() instead.")]
3031
pub struct NetworkInitResult {
3132
/// Network status with IP info.
3233
pub status: NetworkStatus,
@@ -35,17 +36,17 @@ pub struct NetworkInitResult {
3536
/// Network initialization orchestrator (DEPRECATED).
3637
///
3738
/// Network initialization is now handled post-ExitBootServices by
38-
/// `morpheus_network::mainloop::bare_metal_main()`.
39-
#[deprecated(note = "Network init moved to post-EBS. Use bare_metal_main() instead.")]
39+
/// `morpheus_network::mainloop::orchestrator::download_with_config()`.
40+
#[deprecated(note = "Network init moved to post-EBS. Use download_with_config() instead.")]
4041
pub struct NetworkInit;
4142

4243
#[allow(deprecated)]
4344
impl NetworkInit {
4445
/// Perform complete network initialization (DEPRECATED).
4546
///
4647
/// **Always returns error** - network init is now post-EBS.
47-
/// Use `morpheus_network::mainloop::bare_metal_main()` after ExitBootServices.
48-
#[deprecated(note = "Network init moved to post-EBS. Use bare_metal_main() instead.")]
48+
/// Use `morpheus_network::mainloop::download_with_config()` after ExitBootServices.
49+
#[deprecated(note = "Network init moved to post-EBS. Use download_with_config() instead.")]
4950
pub fn initialize(
5051
_config: &InitConfig,
5152
_get_time_ms: fn() -> u64,
@@ -57,7 +58,7 @@ impl NetworkInit {
5758
/// Initialize with display polling (DEPRECATED).
5859
///
5960
/// **Always returns error** - network init is now post-EBS.
60-
#[deprecated(note = "Network init moved to post-EBS. Use bare_metal_main() instead.")]
61+
#[deprecated(note = "Network init moved to post-EBS. Use download_with_config() instead.")]
6162
pub fn initialize_with_poll<F>(
6263
_config: &InitConfig,
6364
_get_time_ms: fn() -> u64,

network/README.md

Lines changed: 94 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -1,101 +1,117 @@
11
# MorpheusX Network Stack
22

3-
HTTP client for downloading ISOs and other files in the UEFI bootloader environment.
3+
Bare-metal HTTP client for post-ExitBootServices execution.
44

5+
## Architecture
56

6-
7-
### Design Principles
8-
9-
1. **Platform Abstraction**: `HttpClient` trait allows multiple implementations
10-
3. **No External Deps**: Everything built on primitives
11-
5. **Error Handling**: Comprehensive error types for network operations
12-
13-
## Usage
14-
15-
### Basic Download
16-
17-
```rust
18-
use morpheus_network::{UefiHttpClient, DownloadManager};
19-
20-
// Create UEFI HTTP client
21-
let mut client = UefiHttpClient::new(boot_services)?;
22-
23-
// Create download manager
24-
let mut downloader = DownloadManager::new(&mut client);
25-
26-
// Download a file
27-
let data = downloader.download_to_memory("http://example.com/file.iso")?;
287
```
29-
30-
### Download with Progress
31-
32-
```rust
33-
fn progress_callback(downloaded: usize, total: Option<usize>) {
34-
if let Some(total) = total {
35-
let percent = (downloaded * 100) / total;
36-
println!("Progress: {}%", percent);
37-
}
38-
}
39-
40-
let data = downloader.download_with_progress(
41-
"http://example.com/large-file.iso",
42-
progress_callback
43-
)?;
8+
┌──────────────────────────────────────────────────────────────┐
9+
│ Entry Point │
10+
│ mainloop::download_with_config(&mut driver, config, ...) │
11+
└──────────────────────────────────────────────────────────────┘
12+
13+
14+
┌──────────────────────────────────────────────────────────────┐
15+
│ State Machine │
16+
│ Init → GptPrep → LinkWait → DHCP → DNS → Connect → HTTP │
17+
└──────────────────────────────────────────────────────────────┘
18+
19+
20+
┌──────────────────────────────────────────────────────────────┐
21+
│ NetworkDriver Trait │
22+
│ transmit(), receive(), mac_address(), link_up() │
23+
└──────────────────────────────────────────────────────────────┘
24+
25+
┌──────────────┴──────────────┐
26+
▼ ▼
27+
┌─────────────────────────┐ ┌─────────────────────────┐
28+
│ VirtioNetDriver │ │ E1000eDriver │
29+
│ (QEMU, KVM) │ │ (Real Hardware) │
30+
└─────────────────────────┘ └─────────────────────────┘
31+
│ │
32+
└──────────────┬──────────────┘
33+
34+
┌──────────────────────────────────────────────────────────────┐
35+
│ ASM Layer (network/asm/) │
36+
│ MMIO read/write, TSC, barriers, cache ops │
37+
└──────────────────────────────────────────────────────────────┘
4438
```
4539

46-
### Check File Size
40+
## Usage
4741

4842
```rust
49-
if let Some(size) = downloader.get_file_size("http://example.com/file.iso")? {
50-
println!("File size: {} bytes", size);
43+
use morpheus_network::mainloop::{download_with_config, DownloadConfig, DownloadResult};
44+
use morpheus_network::boot::probe::{probe_and_create_driver, ProbeResult};
45+
46+
// 1. Probe PCI and create driver (brutal reset happens during driver::new())
47+
let driver = match probe_and_create_driver(&dma, tsc_freq)? {
48+
ProbeResult::Intel(d) => UnifiedNetworkDriver::Intel(d),
49+
ProbeResult::VirtIO(d) => UnifiedNetworkDriver::VirtIO(d),
50+
};
51+
52+
// 2. Configure download
53+
let config = DownloadConfig::full(
54+
"http://example.com/image.iso",
55+
start_sector,
56+
0, // offset
57+
esp_lba,
58+
partition_uuid,
59+
"image.iso",
60+
);
61+
62+
// 3. Execute download with optional disk write
63+
let result = download_with_config(&mut driver, config, Some(blk_device), tsc_freq);
64+
65+
match result {
66+
DownloadResult::Success { bytes_downloaded, bytes_written } => { /* done */ }
67+
DownloadResult::Failed { reason } => { /* handle error */ }
5168
}
5269
```
5370

54-
## Implementation
71+
## Preconditions
5572

56-
### See /docs/
73+
Before calling network functions:
5774

58-
## Error Handling
75+
1. **ExitBootServices completed** - No UEFI runtime
76+
2. **hwinit has run** - Platform normalized (bus mastering, DMA, cache coherency)
77+
3. **DMA region allocated** - Identity-mapped, cache-coherent
5978

60-
All operations return `Result<T, NetworkError>`:
79+
## Driver Reset Contract
6180

62-
```rust
63-
match downloader.download_to_memory(url) {
64-
Ok(data) => { /* success */ },
65-
Err(NetworkError::ProtocolNotAvailable) => {
66-
// UEFI firmware doesn't support HTTP
67-
},
68-
Err(NetworkError::HttpError(404)) => {
69-
// File not found
70-
},
71-
Err(e) => {
72-
// Other error
73-
}
74-
}
75-
```
81+
All drivers perform **brutal reset** on init:
7682

77-
## Testing
83+
- Mask and clear all interrupts
84+
- Disable RX/TX with quiescence polling
85+
- Full device reset with timeout
86+
- Wait for EEPROM auto-read
87+
- Clear all descriptor pointers
88+
- Disable loopback explicitly
89+
- Rebuild queues from scratch
7890

79-
Test in QEMU with OVMF UEFI firmware:
80-
```bash
81-
cd testing
82-
./run.sh
83-
```
84-
85-
Ensure QEMU has network configured:
86-
```bash
87-
-netdev user,id=net0 \
88-
-device e1000,netdev=net0
89-
```
91+
See `driver/RESET_CONTRACT.md` for details.
9092

91-
## Future: ARM Support
93+
## Modules
9294

93-
When adding ARM64 support:
94-
- Same UEFI protocols work on ARM
95-
- No code changes needed in abstraction layer
96-
- May need arch-specific optimizations for large transfers
95+
| Module | Purpose |
96+
|--------|---------|
97+
| `mainloop` | State machine orchestration, entry point |
98+
| `driver` | NetworkDriver trait, VirtIO, Intel e1000e |
99+
| `boot` | Device probing, driver creation helpers |
100+
| `asm` | Assembly bindings (MMIO, PIO, TSC) |
101+
| `dma` | DMA buffer management |
102+
| `time` | TSC-based timing |
97103

98-
## References
104+
## State Machine
99105

100-
- UEFI Specification 2.10, Section 28.7 (EFI HTTP Protocol)
106+
| State | Description |
107+
|-------|-------------|
108+
| Init | Initialize smoltcp interface |
109+
| GptPrep | Prepare GPT if writing to disk |
110+
| LinkWait | Wait for link up |
111+
| DHCP | Obtain IP address |
112+
| DNS | Resolve hostname |
113+
| Connect | TCP connection |
114+
| HTTP | HTTP GET and streaming receive |
115+
| Manifest | Write manifest to disk |
116+
| Done | Reboot |
101117
- UEFI Specification 2.10, Section 11.1 (EFI Service Binding Protocol)

network/src/alloc_heap.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@
2222
//! # Usage
2323
//!
2424
//! ```ignore
25-
//! // In bare_metal_main, before any allocations:
26-
//! unsafe { crate::alloc::init_heap(); }
25+
//! // Early in post-EBS execution, before any allocations:
26+
//! unsafe { morpheus_network::alloc_heap::init_heap(); }
2727
//!
2828
//! // Now Vec, Box, String all work:
2929
//! let v = vec![1, 2, 3];

0 commit comments

Comments
 (0)