1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
// Licensed under the Apache License, Version 2.0 or the MIT License.
// SPDX-License-Identifier: Apache-2.0 OR MIT
// Copyright Tock Contributors 2022.
//! Implementation of the MEMOP family of syscalls.
use crate::process::Process;
use crate::syscall::SyscallReturn;
use crate::ErrorCode;
/// Handle the `memop` syscall.
///
/// ### `memop_num`
///
/// - `0`: BRK. Change the location of the program break and return a
/// SyscallReturn.
/// - `1`: SBRK. Change the location of the program break and return the
/// previous break address.
/// - `2`: Get the address of the start of the application's RAM allocation.
/// - `3`: Get the address pointing to the first address after the end of the
/// application's RAM allocation.
/// - `4`: Get the address of the start of the application's flash region. This
/// is where the TBF header is located.
/// - `5`: Get the address pointing to the first address after the end of the
/// application's flash region.
/// - `6`: Get the address of the lowest address of the grant region for the
/// app.
/// - `7`: Get the number of writeable flash regions defined in the header of
/// this app.
/// - `8`: Get the start address of the writeable region indexed from 0 by r1.
/// Returns (void*) -1 on failure, meaning the selected writeable region
/// does not exist.
/// - `9`: Get the end address of the writeable region indexed by r1. Returns
/// (void*) -1 on failure, meaning the selected writeable region does not
/// exist.
/// - `10`: Specify where the start of the app stack is. This tells the kernel
/// where the app has put the start of its stack. This is not strictly
/// necessary for correct operation, but allows for better debugging if the
/// app crashes.
/// - `11`: Specify where the start of the app heap is. This tells the kernel
/// where the app has put the start of its heap. This is not strictly
/// necessary for correct operation, but allows for better debugging if the
/// app crashes.
pub(crate) fn memop(process: &dyn Process, op_type: usize, r1: usize) -> SyscallReturn {
match op_type {
// Op Type 0: BRK
0 => process
.brk(r1 as *const u8)
.map(|_| SyscallReturn::Success)
.unwrap_or(SyscallReturn::Failure(ErrorCode::NOMEM)),
// Op Type 1: SBRK
1 => process
.sbrk(r1 as isize)
.map(|addr| SyscallReturn::SuccessU32(addr as u32))
.unwrap_or(SyscallReturn::Failure(ErrorCode::NOMEM)),
// Op Type 2: Process memory start
2 => SyscallReturn::SuccessU32(process.get_addresses().sram_start as u32),
// Op Type 3: Process memory end
3 => SyscallReturn::SuccessU32(process.get_addresses().sram_end as u32),
// Op Type 4: Process flash start
4 => SyscallReturn::SuccessU32(process.get_addresses().flash_start as u32),
// Op Type 5: Process flash end
5 => SyscallReturn::SuccessU32(process.get_addresses().flash_end as u32),
// Op Type 6: Grant region begin
6 => SyscallReturn::SuccessU32(process.get_addresses().sram_grant_start as u32),
// Op Type 7: Number of defined writeable regions in the TBF header.
7 => SyscallReturn::SuccessU32(process.number_writeable_flash_regions() as u32),
// Op Type 8: The start address of the writeable region indexed by r1.
8 => {
let flash_start = process.get_addresses().flash_start as u32;
let (offset, size) = process.get_writeable_flash_region(r1);
if size == 0 {
SyscallReturn::Failure(ErrorCode::FAIL)
} else {
SyscallReturn::SuccessU32(flash_start + offset)
}
}
// Op Type 9: The end address of the writeable region indexed by r1.
// Returns (void*) -1 on failure, meaning the selected writeable region
// does not exist.
9 => {
let flash_start = process.get_addresses().flash_start as u32;
let (offset, size) = process.get_writeable_flash_region(r1);
if size == 0 {
SyscallReturn::Failure(ErrorCode::FAIL)
} else {
SyscallReturn::SuccessU32(flash_start + offset + size)
}
}
// Op Type 10: Specify where the start of the app stack is.
10 => {
process.update_stack_start_pointer(r1 as *const u8);
SyscallReturn::Success
}
// Op Type 11: Specify where the start of the app heap is.
11 => {
process.update_heap_start_pointer(r1 as *const u8);
SyscallReturn::Success
}
_ => SyscallReturn::Failure(ErrorCode::NOSUPPORT),
}
}