Software APIs
status.c
1 // Copyright lowRISC contributors (OpenTitan project).
2 // Licensed under the Apache License, Version 2.0, see LICENSE for details.
3 // SPDX-License-Identifier: Apache-2.0
4 
5 #include "sw/device/lib/base/status.h"
6 
7 #include <stdbool.h>
8 #include <stdint.h>
9 
11 
12 const uint32_t MODULE_ID = 0;
13 
14 static const char *basename(const char *file) {
15  const char *f = file;
16  // Go to the end of the string.
17  while (*f)
18  ++f;
19  // Back up to the start of the last filename path component.
20  while (f > file && f[-1] != '/' && f[-1] != '\\')
21  --f;
22  return f;
23 }
24 
25 status_t status_create(absl_status_t code, uint32_t module_id, const char *file,
26  int32_t arg) {
27  if (code == kOk) {
28  if (arg >= 0) {
29  return (status_t){.value = arg};
30  } else {
31  // If you find yourself here, then someone returned a OK_STATUS
32  // a negative value.
33  arg = __LINE__;
34  }
35  }
36  /**
37  * Our status(error) codes are arranged as a packed bitfield:
38  *
39  * 32 31 26 21 16 5 0
40  * +---+-------+-------+-------+-------------+-------+
41  * | | 15 bit | 11 bit | 5 bit |
42  * | s | Module Identifier | Line Number | code |
43  * +---+-------+-------+-------+-------------+-------+
44  *
45  * The sign bit is set on all not-Ok statuses, thus proviging a covenient
46  * overloaded return value from functions that may return an error.
47  */
48  if (module_id == 0) {
49  // First three characters of the filename.
50  const char *f = basename(file);
51  module_id = MAKE_MODULE_ID(f[0], f[1], f[2]);
52  }
53  // At this point, the module_id is already packed into the correct bitfield.
54  return (status_t){
55  .value = (int32_t)(module_id |
56  bitfield_bit32_write(0, STATUS_BIT_ERROR, true) |
57  bitfield_field32_write(0, STATUS_FIELD_CODE, code) |
58  bitfield_field32_write(0, STATUS_FIELD_ARG,
59  (uint32_t)arg))};
60 }
61 
62 const char *status_codes[] = {
63  "Ok",
64  "Cancelled",
65  "Unknown",
66  "InvalidArgument",
67  "DeadlineExceeded",
68  "NotFound",
69  "AlreadyExists",
70  "PermissionDenied",
71  "ResourceExhausted",
72  "FailedPrecondition",
73  "Aborted",
74  "OutOfRange",
75  "Unimplemented",
76  "Internal",
77  "Unavailable",
78  "DataLoss",
79  "Unauthenticated",
80 
81  "Undefined17",
82  "Undefined18",
83  "Undefined19",
84  "Undefined20",
85  "Undefined21",
86  "Undefined22",
87  "Undefined23",
88  "Undefined24",
89  "Undefined25",
90  "Undefined26",
91  "Undefined27",
92  "Undefined28",
93  "Undefined29",
94  "Undefined30",
95  "Undefined31",
96 
97  // A "ErrorError" means the error bit is set but the err field is kOk.
98  "ErrorError",
99 };
100 
101 bool status_extract(status_t s, const char **code, int32_t *arg, char *mod_id) {
102  size_t err = (size_t)status_err(s);
103  if (s.value < 0 && err == 0) {
104  err = sizeof(status_codes) / sizeof(status_codes[0]) - 1;
105  }
106  *code = status_codes[err];
107  if (err) {
108  *arg = (int32_t)bitfield_field32_read((uint32_t)s.value, STATUS_FIELD_ARG);
109  uint32_t module_id =
110  bitfield_field32_read((uint32_t)s.value, STATUS_FIELD_MODULE_ID);
111  *mod_id++ = '@' + ((module_id >> 0) & 0x1F);
112  *mod_id++ = '@' + ((module_id >> 5) & 0x1F);
113  *mod_id++ = '@' + ((module_id >> 10) & 0x1F);
114  return true;
115  } else {
116  *arg = s.value;
117  return false;
118  }
119 }
120 
121 extern bool status_ok(status_t s);
122 extern absl_status_t status_err(status_t s);
123 
124 // This is a weak implementation that does nothing. This way it can easily be
125 // overidden and does not require every user of status to manually add a
126 // dependency.
127 OT_WEAK
128 void status_report(status_t value) { (void)value; }