Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion app/gimlet/rev-b.toml
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,7 @@ uses = [
"usart1",
"system_flash", # TODO also used by `net`, both to read the stm32 uid
]
task-slots = ["jefe", "net", "update_server", "sys"]
task-slots = ["jefe", "net", "update_server", "sys", "hf"]
features = ["gimlet", "usart1", "vlan"]
interrupts = {"usart1.irq" = 0b10}

Expand Down
2 changes: 1 addition & 1 deletion app/gimletlet/app.toml
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ uses = [
"usart1",
"system_flash", # TODO also used by `net`, both to read the stm32 uid
]
task-slots = ["jefe", "net", "update_server", "sys"]
task-slots = ["jefe", "net", "update_server", "sys", "hf"]
features = ["gimlet", "usart1", "vlan"]
interrupts = {"usart1.irq" = 0b10}

Expand Down
3 changes: 2 additions & 1 deletion task/mgmt-gateway/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ num-traits = {version = "0.2", default-features = false}
serde = {version = "1", default-features = false, features = ["derive"]}
ssmarshal = {version = "1", default-features = false}

drv-gimlet-hf-api = {path = "../../drv/gimlet-hf-api"}
drv-stm32h7-usart = {path = "../../drv/stm32h7-usart", features = ["h753"]}
drv-stm32xx-uid = {path = "../../drv/stm32xx-uid", features = ["family-stm32h7"]}
drv-update-api = {path = "../../drv/update-api"}
Expand All @@ -19,7 +20,7 @@ task-jefe-api = {path = "../jefe-api"}
task-net-api = {path = "../net-api", features = ["use-smoltcp"]}
userlib = {path = "../../sys/userlib", features = ["panic-messages"]}

gateway-messages = {git = "https://github.com/oxidecomputer/omicron", rev = "f2e6237e57a36873fc748b6ecd9e42b8ef208c88"}
gateway-messages = {git = "https://github.com/oxidecomputer/omicron", rev = "e6eccffb236d0c242b5f90d30d01daa47aa9d89f"}

[features]
gimlet = []
Expand Down
25 changes: 22 additions & 3 deletions task/mgmt-gateway/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,16 @@
#![no_main]

use gateway_messages::{
sp_impl, sp_impl::Error as MgsDispatchError, IgnitionCommand, SpPort,
sp_impl, sp_impl::Error as MgsDispatchError, IgnitionCommand, SpComponent,
SpPort,
};
use mutable_statics::mutable_statics;
use ringbuf::{ringbuf, ringbuf_entry};
use task_net_api::{
Address, LargePayloadBehavior, Net, RecvError, SendError, SocketName,
UdpMetadata,
};
use userlib::{sys_recv_closed, task_slot, TaskId, UnwrapLite};
use userlib::{sys_recv_closed, sys_set_timer, task_slot, TaskId, UnwrapLite};

mod mgs_common;
mod update_buffer;
Expand Down Expand Up @@ -53,6 +54,7 @@ enum Log {
SerialConsoleSend { buffered: usize },
UpdatePartial { bytes_written: usize },
UpdateComplete,
HostFlashSectorsErased { num_sectors: usize },
}

#[derive(Debug, Clone, Copy, PartialEq)]
Expand All @@ -73,12 +75,23 @@ enum MgsMessage {
length: u16,
},
SerialConsoleDetach,
UpdateStart {
UpdatePrepare {
component: SpComponent,
stream_id: u64,
length: u32,
slot: u16,
},
UpdatePrepareStatus {
component: SpComponent,
stream_id: u64,
},
UpdateChunk {
component: SpComponent,
offset: u32,
},
UpdateAbort {
component: SpComponent,
},
SysResetPrepare,
}

Expand All @@ -99,6 +112,8 @@ fn main() {
let mut net_handler = NetHandler::claim_static_resources();

loop {
sys_set_timer(mgs_handler.timer_deadline(), TIMER_IRQ);

let note = sys_recv_closed(
&mut [],
NET_IRQ | USART_IRQ | TIMER_IRQ,
Expand All @@ -112,6 +127,10 @@ fn main() {
mgs_handler.drive_usart();
}

if (note & TIMER_IRQ) != 0 {
mgs_handler.handle_timer_fired();
}

if (note & NET_IRQ) != 0 || mgs_handler.wants_to_send_packet_to_mgs() {
net_handler.run_until_blocked(&mut mgs_handler);
}
Expand Down
58 changes: 45 additions & 13 deletions task/mgmt-gateway/src/mgs_common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ use core::convert::Infallible;
use drv_update_api::stm32h7::BLOCK_SIZE_BYTES;
use drv_update_api::{Update, UpdateTarget};
use gateway_messages::{
DiscoverResponse, ResponseError, SpPort, SpState, UpdateChunk, UpdateStart,
DiscoverResponse, ResponseError, SpComponent, SpPort, SpState, UpdateChunk,
UpdatePrepare, UpdatePrepareStatusRequest, UpdatePrepareStatusResponse,
};
use ringbuf::ringbuf_entry_root;

Expand Down Expand Up @@ -73,36 +74,68 @@ impl MgsCommon {
})
}

pub(crate) fn update_start(
pub(crate) fn update_prepare(
&mut self,
update: UpdateStart,
update: UpdatePrepare,
) -> Result<(), ResponseError> {
ringbuf_entry_root!(Log::MgsMessage(MgsMessage::UpdateStart {
length: update.total_size
}));
// We should only be called to update the SP itself.
if update.component != SpComponent::SP_ITSELF {
panic!();
}

// SP only has one "slot" (the alternate bank).
if update.slot != 0 {
return Err(ResponseError::InvalidSlotForComponent);
}

self.update_buf.ensure_no_update_in_progress()?;

self.update_task
.prep_image_update(UpdateTarget::Alternate)
.map_err(|err| ResponseError::UpdateFailed(err as u32))?;

self.update_buf.start(update.total_size as usize);
self.update_buf
.start(update.stream_id, update.total_size as usize);

Ok(())
}

pub(crate) fn update_prepare_status(
&mut self,
request: UpdatePrepareStatusRequest,
) -> Result<UpdatePrepareStatusResponse, ResponseError> {
self.update_buf
.ensure_matching_stream_id(request.stream_id)?;

// We immediately prepare for update in `update_prepare()`
// and have no followup work to do; if this stream ID
// matches, we're already prepared.
Ok(UpdatePrepareStatusResponse { done: true })
}

pub(crate) fn update_chunk(
&mut self,
chunk: UpdateChunk,
data: &[u8],
) -> Result<(), ResponseError> {
ringbuf_entry_root!(Log::MgsMessage(MgsMessage::UpdateChunk {
offset: chunk.offset,
}));

self.update_buf
.ingest_chunk(&self.update_task, chunk.offset, data)
.ingest_chunk(
chunk.stream_id,
&self.update_task,
chunk.offset,
data,
)
.map(|_progress| ())
}

pub(crate) fn update_abort(&mut self) -> Result<(), ResponseError> {
self.update_task
.abort_update()
.map_err(|err| ResponseError::UpdateFailed(err as u32))?;

self.update_buf.reset();

Ok(())
}

pub(crate) fn reset_prepare(&mut self) -> Result<(), ResponseError> {
Expand Down Expand Up @@ -130,7 +163,6 @@ impl MgsCommon {
}
}

/// Grabs reference to a static `UpdateBuffer`. Can only be called once!
fn claim_update_buffer_static(
) -> &'static mut heapless::Vec<u8, BLOCK_SIZE_BYTES> {
use core::sync::atomic::{AtomicBool, Ordering};
Expand Down
Loading