(* * Copyright 2014, NICTA * * This software may be distributed and modified according to the terms of * the GNU General Public License version 2. Note that NO WARRANTY is provided. * See "LICENSE_GPLv2.txt" for details. * * @TAG(NICTA_GPL) *) theory Glue_CAMKES imports Types_CAMKES begin abbreviation "seL4_MsgMaxLength \ 120::nat" type_synonym ipc = "nat list" definition wellformed_ipc :: "ipc \ bool" where "wellformed_ipc i = (length i < seL4_MsgMaxLength)" (* FIXME: These definitions need to diverge from the implementation definitions because we * need to distinguish between primitive types and things like strings. The implementation * does this in a pretty ad hoc way. *) record parameter_value = p_type :: param_type p_value :: "nat list" (* FIXME: Better type for generic values. *) definition wellformed_parameter :: "parameter_value \ bool" where "wellformed_parameter p = (case p_type p of Primitive _ \ length (p_value p) = 1 | Array t \ (case t of SizedArray _ \ True | TerminatedArray _ \ length (p_value p) > 0 \ hd (rev (p_value p)) = 0))" abbreviation "prim_value \ \(x::parameter_value). hd (p_value x)" definition marshal_primitive :: "ipc \ parameter_value \ ipc" where "marshal_primitive i p = i @ [hd (p_value p)]" (* TODO: The implementation does some optimisations that are not represented in these * definitions (e.g. packing multiple chars into a single message register). *) function marshal_array :: "ipc \ parameter_value \ ipc" where "marshal_array i p = (case p_value p of [] \ i | _ # xs \ marshal_array (marshal_primitive i p) \p_type = p_type p, p_value = xs\)" by fast+ definition marshal :: "ipc \ parameter_value \ ipc" where "marshal i p = (case p_type p of Primitive _ \ marshal_primitive i p |Array _ \ marshal_array i p)" definition unmarshal_primitive :: "ipc \ primitive \ parameter_value \ ipc" where "unmarshal_primitive i t = (\p_type = Primitive t, p_value = [hd i]\, tl i)" fun unmarshal_array_by_size :: "ipc \ primitive \ nat \ nat list \ parameter_value \ ipc" where "unmarshal_array_by_size i t 0 ac = (\p_type = Array (SizedArray t), p_value = ac\, i)" |"unmarshal_array_by_size i t sz ac = unmarshal_array_by_size (snd (unmarshal_primitive i t)) t (sz - 1) (ac @ p_value (fst (unmarshal_primitive i t)))" function unmarshal_array_by_terminator :: "ipc \ primitive \ nat list \ parameter_value \ ipc" where "unmarshal_array_by_terminator i t ac = (case (prim_value (fst (unmarshal_primitive i t))) of 0 \ (\p_type = Array (TerminatedArray t), p_value = ac @ [0]\, snd (unmarshal_primitive i t)) |_ \ unmarshal_array_by_terminator (snd (unmarshal_primitive i t)) t (ac @ p_value (fst (unmarshal_primitive i t))))" by fast+ definition unmarshal_array :: "ipc \ primitive \ nat option \ parameter_value \ ipc" where "unmarshal_array i t n = (case n of None \ unmarshal_array_by_terminator i t [] |Some nn \ unmarshal_array_by_size i t nn [])" (* Some sanity checks *) (* Marshalling something into an empty IPC and then unmarshalling it does not * alter the value or the IPC. *) lemma "\marshal_primitive [] p = i2; wellformed_parameter p; p_type p = Primitive q; unmarshal_primitive i2 q = (n, i3)\ \ wellformed_ipc i2 \ [] = i3 \ n = p" apply (simp add:marshal_primitive_def unmarshal_primitive_def) apply (clarsimp simp:wellformed_ipc_def wellformed_parameter_def) apply (induct p, clarsimp, case_tac p_value, simp+) done (* Unmarshalling anything from an empty IPC gives you nothing. *) lemma "\t. \p. (unmarshal_primitive [] t = (\p_type = p, p_value = [hd []]\, []))" by (simp add:unmarshal_primitive_def) (* TODO: Definitions of send/receive as basically thin wrappers around the syscalls. *) (* TODO: Definitions of the connectors' operations in terms of send and receive. *) end