Quelle hwrng_service.c Sprache: unbekannt
/*
* Copyright ( c ) 2022 , Google Inc . All rights reserved
*
* Permission is hereby granted , free of charge , to any person obtaining
* a copy of this software and associated documentation files
* ( the " Software " ) , to deal in the Software without restriction ,
* including without limitation the rights to use , copy , modify , merge ,
* publish , distribute , sublicense , and / or sell copies of the Software ,
* and to permit persons to whom the Software is furnished to do so ,
* subject to the following conditions :
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software .
*
* THE SOFTWARE IS PROVIDED " AS IS " , WITHOUT WARRANTY OF ANY KIND ,
* EXPRESS OR IMPLIED , INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY , FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT .
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM , DAMAGES OR OTHER LIABILITY , WHETHER IN AN ACTION OF CONTRACT ,
* TORT OR OTHERWISE , ARISING FROM , OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE .
*/
#define LOCAL_TRACE 0
#include <err.h>
#include <inttypes.h>
#include <lib/ktipc/ktipc.h>
#include <lib/rand/rand.h>
#include <lib/trusty/ipc.h>
#include <lib/trusty/ipc_msg.h>
#include <lib/trusty/uuid.h>
#include <lk/init.h>
#include <lk/list.h>
#include <lk/trace.h>
#include <interface/hwrng/hwrng.h>
#define HWRNG_SRV_NAME HWRNG_PORT
#define MAX_HWRNG_MSG_SIZE 128
struct hwrng_chan_ctx {
struct list_node node;
struct handle* chan;
size_t req_size;
int error;
bool send_blocked;
};
static uint8_t rng_data[MAX_HWRNG_MSG_SIZE];
/* If we have data left over from the last request, keep track of it */
static size_t rng_data_avail_count;
static size_t rng_data_avail_pos;
static struct list_node hwrng_req_list = LIST_INITIAL_VALUE(hwrng_req_list);
/*
* Handle HWRNG request queue
*/
static void hwrng_handle_req_queue(void ) {
int rc;
struct hwrng_chan_ctx* ctx;
struct hwrng_chan_ctx* temp;
/* for all pending requests */
bool more_requests;
do {
more_requests = false ;
list_for_every_entry_safe(&hwrng_req_list, ctx, temp,
struct hwrng_chan_ctx, node) {
if (ctx->error || ctx->send_blocked)
continue ; /* can't service it right now */
/*
* send up to MAX_HWRNG_MSG_SIZE per client at a time ,
* to prevent a single client from starving all the others
*/
size_t len = MIN(ctx->req_size, MAX_HWRNG_MSG_SIZE);
if (rng_data_avail_count) {
/* use leftover data if there is any */
len = MIN(len, rng_data_avail_count);
} else {
/* get hwrng data */
rand_get_bytes(rng_data, len);
rng_data_avail_pos = 0 ;
rng_data_avail_count = len;
}
/* send reply */
rc = ktipc_send(ctx->chan, rng_data + rng_data_avail_pos, len);
if (rc < 0 ) {
if (rc == ERR_NOT_ENOUGH_BUFFER) {
/* mark it as send_blocked */
ctx->send_blocked = true ;
} else {
TRACEF("%s: failed (%d) to send_reply\n" , __func__, rc);
ctx->error = rc;
}
continue ;
}
rng_data_avail_pos += len;
rng_data_avail_count -= len;
ctx->req_size -= len;
if (!ctx->req_size) {
/* remove it from pending list */
list_delete(&ctx->node);
} else {
more_requests = true ;
}
}
} while (more_requests);
}
static int hwrng_handle_msg(const struct ktipc_port* port,
struct handle* chan,
void * ctx_v) {
int rc;
struct hwrng_chan_ctx* ctx = ctx_v;
struct hwrng_req req;
/* check for an error from a previous send attempt */
if (ctx->error) {
return ctx->error;
}
/* read request */
rc = ktipc_recv(chan, sizeof (req), &req, sizeof (req));
if (rc < 0 ) {
TRACEF("%s: failed (%d) to receive msg for chan\n" , __func__, rc);
return rc;
}
/* check if we already have request in progress */
if (list_in_list(&ctx->node)) {
/* extend it */
ctx->req_size += req.len;
} else {
/* queue it */
ctx->req_size = req.len;
list_add_tail(&hwrng_req_list, &ctx->node);
}
hwrng_handle_req_queue();
return ctx->error;
}
static int hwrng_handle_connect(const struct ktipc_port* port,
struct handle* chan,
const struct uuid* peer,
void ** ctx_p) {
struct hwrng_chan_ctx* ctx = calloc(1 , sizeof (*ctx));
if (!ctx) {
TRACEF("%s: failed to allocate context\n" , __func__);
return ERR_NO_MEMORY;
}
ctx->chan = chan;
*ctx_p = ctx;
return NO_ERROR;
}
static void hwrng_handle_channel_cleanup(void * ctx_v) {
struct hwrng_chan_ctx* ctx = ctx_v;
if (list_in_list(&ctx->node)) {
list_delete(&ctx->node);
}
free(ctx);
}
static int hwrng_handle_send_unblocked(const struct ktipc_port* port,
struct handle* chan,
void * ctx_v) {
struct hwrng_chan_ctx* ctx = ctx_v;
if (ctx->error) {
return ctx->error;
}
ctx->send_blocked = false ;
hwrng_handle_req_queue();
return ctx->error;
}
const static struct ktipc_srv_ops hwrng_srv_ops = {
.on_connect = hwrng_handle_connect,
.on_message = hwrng_handle_msg,
.on_channel_cleanup = hwrng_handle_channel_cleanup,
.on_send_unblocked = hwrng_handle_send_unblocked,
};
const static struct ktipc_port_acl hwrng_srv_port_acl = {
.flags = IPC_PORT_ALLOW_TA_CONNECT,
.uuids = NULL,
.uuid_num = 0 ,
.extra_data = NULL,
};
const static struct ktipc_port hwrng_srv_port = {
.name = HWRNG_SRV_NAME,
.uuid = &kernel_uuid,
.msg_max_size = MAX_HWRNG_MSG_SIZE,
.msg_queue_len = 1 ,
.acl = &hwrng_srv_port_acl,
.priv = NULL,
};
static struct ktipc_server hwrng_ktipc_server =
KTIPC_SERVER_INITIAL_VALUE(hwrng_ktipc_server, "hwrng_ktipc_server" );
static void hwrng_ktipc_server_init(uint lvl) {
int rc;
rc = ktipc_server_start(&hwrng_ktipc_server);
if (rc < 0 ) {
panic("Failed (%d) to start hwrng server\n" , rc);
}
rc = ktipc_server_add_port(&hwrng_ktipc_server, &hwrng_srv_port,
&hwrng_srv_ops);
if (rc < 0 ) {
panic("Failed (%d) to create hwrng service port\n" , rc);
}
}
LK_INIT_HOOK(hwrng_ktipc_server_init,
hwrng_ktipc_server_init,
LK_INIT_LEVEL_APPS - 1 )
Messung V0.5 in Prozent C=87 H=89 G=87
[Dauer der Verarbeitung: 0.18 Sekunden, vorverarbeitet 2026-09-27]
2026-10-10
Neuigkeiten
Aktuelles
Motto des Tages
Open Source Software
Jenseits des Üblichen ....
Besucherstatistik
Statistik
#Sources=1126864
#Domains=2039723