/* This assumes that bufs and buf_copy are copies from the values passed * as syscall arguments. */ static void copy_and_check(struct spi_buf_set *bufs, struct spi_buf *buf_copy, int writable, void *ssf) { size_t i; if (bufs->count == 0) { bufs->buffers = NULL; return; } /* Validate the array of struct spi_buf instances */ Z_OOPS(Z_SYSCALL_MEMORY_ARRAY_READ(bufs->buffers, bufs->count, sizeof(struct spi_buf))); /* Not worried abuot overflow here: _SYSCALL_MEMORY_ARRAY_READ() * takes care of it. */ bufs->buffers = memcpy(buf_copy, bufs->buffers, bufs->count * sizeof(struct spi_buf)); for (i = 0; i < bufs->count; i++) { /* Now for each array element, validate the memory buffers * that they point to */ const struct spi_buf *buf = &bufs->buffers[i]; Z_OOPS(Z_SYSCALL_MEMORY(buf->buf, buf->len, writable)); } }
Z_SYSCALL_HANDLER(spi_release, dev, config_p) { const struct spi_config *config = (const struct spi_config *)config_p; Z_OOPS(Z_SYSCALL_MEMORY_READ(config, sizeof(*config))); Z_OOPS(Z_SYSCALL_DRIVER_SPI(dev, release)); return _impl_spi_release((struct device *)dev, config); }
Z_SYSCALL_HANDLER(spi_transceive, dev, config_p, tx_bufs, rx_bufs) { const struct spi_config *config = (const struct spi_config *)config_p; struct spi_buf_set tx_bufs_copy; struct spi_buf_set rx_bufs_copy; struct spi_config config_copy; Z_OOPS(Z_SYSCALL_MEMORY_READ(config, sizeof(*config))); Z_OOPS(Z_SYSCALL_DRIVER_SPI(dev, transceive)); if (tx_bufs) { const struct spi_buf_set *tx = (const struct spi_buf_set *)tx_bufs; Z_OOPS(Z_SYSCALL_MEMORY_READ(tx_bufs, sizeof(struct spi_buf_set))); memcpy(&tx_bufs_copy, tx, sizeof(tx_bufs_copy)); Z_OOPS(Z_SYSCALL_VERIFY(tx_bufs_copy.count < 32)); } else { memset(&tx_bufs_copy, 0, sizeof(tx_bufs_copy)); } if (rx_bufs) { const struct spi_buf_set *rx = (const struct spi_buf_set *)rx_bufs; Z_OOPS(Z_SYSCALL_MEMORY_READ(rx_bufs, sizeof(struct spi_buf_set))); memcpy(&rx_bufs_copy, rx, sizeof(rx_bufs_copy)); Z_OOPS(Z_SYSCALL_VERIFY(rx_bufs_copy.count < 32)); } else { memset(&rx_bufs_copy, 0, sizeof(rx_bufs_copy)); } memcpy(&config_copy, config, sizeof(*config)); if (config_copy.cs) { const struct spi_cs_control *cs = config_copy.cs; Z_OOPS(Z_SYSCALL_MEMORY_READ(cs, sizeof(*cs))); if (cs->gpio_dev) { Z_OOPS(Z_SYSCALL_OBJ(cs->gpio_dev, K_OBJ_DRIVER_GPIO)); } } /* ssf is implicit system call stack frame parameter, used by * _SYSCALL_* APIs when something goes wrong. */ return copy_bufs_and_transceive((struct device *)dev, &config_copy, &tx_bufs_copy, &rx_bufs_copy, ssf); }
Z_SYSCALL_HANDLER(hwinfo_get_device_id, buffer, length) { Z_OOPS(Z_SYSCALL_MEMORY_WRITE(buffer, length)); return _impl_hwinfo_get_device_id((u8_t *)buffer, (size_t)length); }
Z_SYSCALL_HANDLER(rtc_get_pending_int, dev) { Z_OOPS(Z_SYSCALL_DRIVER_RTC(dev, get_pending_int)); return z_impl_rtc_get_pending_int((struct device *)dev); }
Z_SYSCALL_HANDLER(rtc_read, dev) { Z_OOPS(Z_SYSCALL_DRIVER_RTC(dev, read)); return z_impl_rtc_read((struct device *)dev); }
Z_SYSCALL_HANDLER(rtc_set_alarm, dev, alarm_val) { Z_OOPS(Z_SYSCALL_DRIVER_RTC(dev, set_alarm)); return z_impl_rtc_set_alarm((struct device *)dev, alarm_val); }
Z_SYSCALL_HANDLER(rtc_disable, dev) { Z_OOPS(Z_SYSCALL_DRIVER_RTC(dev, disable)); z_impl_rtc_disable((struct device *)dev); return 0; }
Z_SYSCALL_HANDLER(led_blink, dev, led, delay_on, delay_off) { Z_OOPS(Z_SYSCALL_DRIVER_LED(dev, blink)); return z_impl_led_blink((struct device *)dev, led, delay_on, delay_off); }
Z_SYSCALL_HANDLER(led_off, dev, led) { Z_OOPS(Z_SYSCALL_DRIVER_LED(dev, off)); return z_impl_led_off((struct device *)dev, led); }
Z_SYSCALL_HANDLER(led_set_brightness, dev, led, value) { Z_OOPS(Z_SYSCALL_DRIVER_LED(dev, set_brightness)); return z_impl_led_set_brightness((struct device *)dev, led, value); }