|
| 1 | +/* |
| 2 | + * This file is part of AtomVM. |
| 3 | + * |
| 4 | + * Copyright 2023 Paul Guyot <[email protected]> |
| 5 | + * |
| 6 | + * Licensed under the Apache License, Version 2.0 (the "License"); |
| 7 | + * you may not use this file except in compliance with the License. |
| 8 | + * You may obtain a copy of the License at |
| 9 | + * |
| 10 | + * http://www.apache.org/licenses/LICENSE-2.0 |
| 11 | + * |
| 12 | + * Unless required by applicable law or agreed to in writing, software |
| 13 | + * distributed under the License is distributed on an "AS IS" BASIS, |
| 14 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 15 | + * See the License for the specific language governing permissions and |
| 16 | + * limitations under the License. |
| 17 | + * |
| 18 | + * SPDX-License-Identifier: Apache-2.0 OR LGPL-2.1-or-later |
| 19 | + */ |
| 20 | + |
| 21 | +#include <sdkconfig.h> |
| 22 | +#ifdef CONFIG_AVM_ENABLE_RTC_SLOW_NIFS |
| 23 | + |
| 24 | +#include <atom.h> |
| 25 | +#include <defaultatoms.h> |
| 26 | +#include <interop.h> |
| 27 | +#include <memory.h> |
| 28 | +#include <nifs.h> |
| 29 | +#include <stdlib.h> |
| 30 | +#include <term.h> |
| 31 | + |
| 32 | +#include <rom/crc.h> |
| 33 | + |
| 34 | +#include "esp32_sys.h" |
| 35 | + |
| 36 | +//#define ENABLE_TRACE |
| 37 | +#include "trace.h" |
| 38 | + |
| 39 | +#ifndef CONFIG_AVM_RTC_SLOW_MAX_SIZE |
| 40 | +#define CONFIG_AVM_RTC_SLOW_MAX_SIZE 4086 |
| 41 | +#endif |
| 42 | + |
| 43 | +// Ensure checksum is incorrect when memory is zeroed. |
| 44 | +#define RTC_SLOW_CRC32_MAGIC 0x55555555 |
| 45 | + |
| 46 | +RTC_NOINIT_ATTR uint32_t rtc_slow_data_checksum; |
| 47 | +RTC_NOINIT_ATTR uint16_t rtc_slow_data_size; |
| 48 | +RTC_NOINIT_ATTR uint8_t rtc_slow_data[CONFIG_AVM_RTC_SLOW_MAX_SIZE]; |
| 49 | + |
| 50 | +static void rtc_slow_nif_init(GlobalContext *global); |
| 51 | +static const struct Nif *rtc_slow_nif_get_nif(const char *nifname); |
| 52 | + |
| 53 | +static term nif_esp_rtc_slow_get_binary(Context *ctx, int argc, term argv[]) |
| 54 | +{ |
| 55 | + UNUSED(argc); |
| 56 | + UNUSED(argv); |
| 57 | + if (rtc_slow_data_size > sizeof(rtc_slow_data)) { |
| 58 | + RAISE_ERROR(BADARG_ATOM); |
| 59 | + } |
| 60 | + uint32_t checksum = crc32_le(RTC_SLOW_CRC32_MAGIC, rtc_slow_data, rtc_slow_data_size); |
| 61 | + if (checksum != rtc_slow_data_checksum) { |
| 62 | + RAISE_ERROR(BADARG_ATOM); |
| 63 | + } |
| 64 | + if (UNLIKELY(memory_ensure_free(ctx, term_binary_data_size_in_terms(rtc_slow_data_size) + BINARY_HEADER_SIZE) != MEMORY_GC_OK)) { |
| 65 | + RAISE_ERROR(OUT_OF_MEMORY_ATOM); |
| 66 | + } |
| 67 | + |
| 68 | + return term_from_literal_binary(rtc_slow_data, rtc_slow_data_size, ctx); |
| 69 | +} |
| 70 | + |
| 71 | +static term nif_esp_rtc_slow_set_binary(Context *ctx, int argc, term argv[]) |
| 72 | +{ |
| 73 | + UNUSED(argc); |
| 74 | + VALIDATE_VALUE(argv[0], term_is_binary); |
| 75 | + term binary = argv[0]; |
| 76 | + size_t size = term_binary_size(binary); |
| 77 | + if (size > sizeof(rtc_slow_data)) { |
| 78 | + RAISE_ERROR(BADARG_ATOM); |
| 79 | + } |
| 80 | + const uint8_t *data = (const uint8_t *) term_binary_data(binary); |
| 81 | + rtc_slow_data_checksum = crc32_le(RTC_SLOW_CRC32_MAGIC, data, size); |
| 82 | + rtc_slow_data_size = size; |
| 83 | + memcpy(rtc_slow_data, data, size); |
| 84 | + |
| 85 | + return OK_ATOM; |
| 86 | +} |
| 87 | + |
| 88 | +static const struct Nif esp_rtc_slow_get_binary_nif = { |
| 89 | + .base.type = NIFFunctionType, |
| 90 | + .nif_ptr = nif_esp_rtc_slow_get_binary |
| 91 | +}; |
| 92 | +static const struct Nif esp_rtc_slow_set_binary_nif = { |
| 93 | + .base.type = NIFFunctionType, |
| 94 | + .nif_ptr = nif_esp_rtc_slow_set_binary |
| 95 | +}; |
| 96 | + |
| 97 | +void rtc_slow_nif_init(GlobalContext *gloabl) |
| 98 | +{ |
| 99 | + // no-op |
| 100 | +} |
| 101 | + |
| 102 | +const struct Nif *rtc_slow_nif_get_nif(const char *nifname) |
| 103 | +{ |
| 104 | + if (strcmp("esp:rtc_slow_get_binary/0", nifname) == 0) { |
| 105 | + TRACE("Resolved platform nif %s ...\n", nifname); |
| 106 | + return &esp_rtc_slow_get_binary_nif; |
| 107 | + } |
| 108 | + if (strcmp("esp:rtc_slow_set_binary/1", nifname) == 0) { |
| 109 | + TRACE("Resolved platform nif %s ...\n", nifname); |
| 110 | + return &esp_rtc_slow_set_binary_nif; |
| 111 | + } |
| 112 | + return NULL; |
| 113 | +} |
| 114 | + |
| 115 | +REGISTER_NIF_COLLECTION(rtc_slow, rtc_slow_nif_init, rtc_slow_nif_get_nif) |
| 116 | + |
| 117 | +#endif |
0 commit comments