1 /* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
2 
3 /* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
4    Copyright (c) 2006 - 2013 Thomas Schmitt <scdbackup@gmx.net>
5    Provided under GPL version 2 or later.
6 */
7 
8 #ifdef HAVE_CONFIG_H
9 #include "../config.h"
10 #endif
11 
12 
13 #include <unistd.h>
14 
15 /* ts A61007 */
16 /* #include <a ssert.h> */
17 
18 #include <stdio.h>
19 #include <signal.h>
20 #include <string.h>
21 #include <stdlib.h>
22 #include <pthread.h>
23 
24 /* ts A70928 : init.h is for others, not for init .c
25 #include "init.h"
26 */
27 
28 
29 #include "sg.h"
30 #include "error.h"
31 #include "libburn.h"
32 #include "drive.h"
33 #include "transport.h"
34 #include "util.h"
35 
36 /* ts A60825 : The storage location for back_hacks.h variables. */
37 #define BURN_BACK_HACKS_INIT 1
38 #include "back_hacks.h"
39 
40 /* ts A60924 : a new message handling facility */
41 #include "libdax_msgs.h"
42 struct libdax_msgs *libdax_messenger= NULL;
43 
44 
45 int burn_running = 0;
46 
47 double lib_start_time;
48 
49 
50 /* ts A60813 : GNU/Linux: whether to use O_EXCL on open() of device files
51    ts B00212 : FreeBSD:   whether to use flock(LOCK_EX) after open()
52 */
53 int burn_sg_open_o_excl = 1;
54 
55 /* ts A70403 : GNU/Linux: whether to use fcntl(,F_SETLK,)
56                       after open() of device files  */
57 int burn_sg_fcntl_f_setlk = 1;
58 
59 /* ts A70314 : GNU/Linux: what device family to use :
60     0= default family
61     1= sr
62     2= scd
63    (3= st)
64     4= sg
65 */
66 int burn_sg_use_family = 0;
67 
68 /* O_NONBLOCK was hardcoded in enumerate_ata() which i hardly use.
69    For enumerate_sg() it seems ok.
70    So it should stay default mode until enumerate_ata() without O_NONBLOCK
71    has been thoroughly tested. */
72 int burn_sg_open_o_nonblock = 1;
73 
74 /* whether to take a busy drive as an error */
75 /* Caution: this is implemented by a rough hack and eventually leads
76 	    to unconditional abort of the process  */
77 int burn_sg_open_abort_busy = 0;
78 
79 
80 /* The message returned from sg_id_string() and/or sg_initialize()
81 */
82 static char sg_initialize_msg[1024] = {""};
83 
84 
85 /* ts A61002 */
86 
87 #include "cleanup.h"
88 
89 /* Parameters for builtin abort handler */
90 static char abort_message_prefix[81] = {"libburn : "};
91 static pid_t abort_control_pid= 0;
92 static pthread_t abort_control_thread;
93 volatile int burn_global_abort_level= 0;
94 int burn_global_abort_signum= 0;
95 void *burn_global_signal_handle = NULL;
96 burn_abort_handler_t burn_global_signal_handler = NULL;
97 int burn_builtin_signal_action = 0;            /* burn_set_signal_handling() */
98 volatile int burn_builtin_triggered_action = 0;       /*  burn_is_aborting() */
99 
100 
101 /* ts A70223 : whether implemented untested profiles are supported */
102 int burn_support_untested_profiles = 0;
103 
104 /* ts A91111 :
105    whether to log SCSI commands (to be implemented in sg-*.c)
106    bit0= log in /tmp/libburn_sg_command_log
107    bit1= log to stderr
108    bit2= flush every line
109 */
110 int burn_sg_log_scsi = 0;
111 
112 
113 /* ts B10312 :
114    Whether to map random-access readonly files to drive role 4.
115    Else it is role 2 overwritable drive
116 */
117 int burn_drive_role_4_allowed = 0;
118 
119 
120 /* ts A60925 : ticket 74 */
121 /** Create the messenger object for libburn. */
burn_msgs_initialize(void)122 int burn_msgs_initialize(void)
123 {
124 	int ret;
125 
126 	if(libdax_messenger == NULL) {
127 		ret = libdax_msgs_new(&libdax_messenger,0);
128 		if (ret <= 0)
129 			return 0;
130 	}
131 	libdax_msgs_set_severities(libdax_messenger, LIBDAX_MSGS_SEV_NEVER,
132 				   LIBDAX_MSGS_SEV_FATAL, "libburn: ", 0);
133 	return 1;
134 }
135 
136 /* ts A60924 : ticket 74 : Added use of global libdax_messenger */
burn_initialize(void)137 int burn_initialize(void)
138 {
139 	int ret;
140 
141 	if (burn_running)
142 		return 1;
143 
144 	lib_start_time = burn_get_time(0);
145 	burn_support_untested_profiles = 0;
146 	ret = burn_msgs_initialize();
147 	if (ret <= 0)
148 		return 0;
149 	ret = sg_initialize(sg_initialize_msg, 0);
150 	if (ret <= 0) {
151                 libdax_msgs_submit(libdax_messenger, -1,
152                         0x00020175,
153                         LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
154                         sg_initialize_msg, 0, 0);
155 		return 0;
156 	}
157 	burn_running = 1;
158 	return 1;
159 }
160 
burn_finish(void)161 void burn_finish(void)
162 {
163 	/* ts A61007 : assume no messageing system */
164 	/* a ssert(burn_running); */
165 	if (!burn_running)
166 		return;
167 
168 	/* ts A61007 */
169 	/* burn_wait_all(); */
170 	if (!burn_drives_are_clear(0)) {
171 		libdax_msgs_submit(libdax_messenger, -1, 0x00020107,
172 			LIBDAX_MSGS_SEV_WARNING, LIBDAX_MSGS_PRIO_HIGH,
173 			"A drive is still busy on shutdown of library", 0, 0);
174 		usleep(1000001);
175 		burn_abort(4440, burn_abort_pacifier, abort_message_prefix);
176 	}
177 
178 	/* ts A60904 : ticket 62, contribution by elmom : name addon "_all" */
179 	burn_drive_free_all();
180 
181 	/* ts A60924 : ticket 74 */
182 	libdax_msgs_destroy(&libdax_messenger,0);
183 
184 	sg_shutdown(0);
185 
186 	burn_drive_clear_whitelist();
187 
188 	burn_running = 0;
189 }
190 
191 
192 /* ts A91226 */
193 /** API function. See libburn.h */
burn_scsi_transport_id(int flag)194 char *burn_scsi_transport_id(int flag)
195 {
196 	if (!burn_running)
197 		sg_id_string(sg_initialize_msg, 0);
198 	return sg_initialize_msg;
199 }
200 
201 
202 /* ts A60813 */
203 /** API function. See libburn.h */
burn_preset_device_open(int exclusive,int blocking,int abort_on_busy)204 void burn_preset_device_open(int exclusive, int blocking, int abort_on_busy)
205 {
206 	/* ts A61007 */
207 	/* a ssert(burn_running); */
208 	if (!burn_running)
209 		return;
210 	burn_sg_open_o_excl = exclusive & 3;
211 	burn_sg_fcntl_f_setlk = !!(exclusive & 32);
212 	burn_sg_use_family = (exclusive >> 2) & 7;
213 	burn_sg_open_o_nonblock = !blocking;
214 	burn_sg_open_abort_busy = !!abort_on_busy;
215 }
216 
217 
218 /* ts A60924 : ticket 74 */
219 /** Control queueing and stderr printing of messages from libburn.
220     Severity may be one of "NEVER", "FATAL", "SORRY", "WARNING", "HINT",
221     "NOTE", "UPDATE", "DEBUG", "ALL".
222     @param queue_severity Gives the minimum limit for messages to be queued.
223                           Default: "NEVER". If you queue messages then you
224                           must consume them by burn_msgs_obtain().
225     @param print_severity Does the same for messages to be printed directly
226                           to stderr.
227     @param print_id       A text prefix to be printed before the message.
228     @return               >0 for success, <=0 for error
229 
230 */
burn_msgs_set_severities(char * queue_severity,char * print_severity,char * print_id)231 int burn_msgs_set_severities(char *queue_severity,
232                              char *print_severity, char *print_id)
233 {
234 	int ret, queue_sevno, print_sevno;
235 
236 	ret = libdax_msgs__text_to_sev(queue_severity, &queue_sevno, 0);
237 	if (ret <= 0)
238 		return 0;
239 	ret = libdax_msgs__text_to_sev(print_severity, &print_sevno, 0);
240 	if (ret <= 0)
241 		return 0;
242 	ret = libdax_msgs_set_severities(libdax_messenger, queue_sevno,
243 					 print_sevno, print_id, 0);
244 	if (ret <= 0)
245 		return 0;
246 	return 1;
247 }
248 
249 
250 /* ts A60924 : ticket 74 */
251 #define BURM_MSGS_MESSAGE_LEN 4096
252 
253 /** Obtain the oldest pending libburn message from the queue which has at
254     least the given minimum_severity. This message and any older message of
255     lower severity will get discarded from the queue and is then lost forever.
256     Severity may be one of "NEVER", "FATAL", "SORRY", "WARNING", "HINT",
257     "NOTE", "UPDATE", "DEBUG", "ALL". To call with minimum_severity "NEVER"
258     will discard the whole queue.
259     @param error_code Will become a unique error code as liste in
260                       libburn/libdax_msgs.h
261     @param msg_text   Must provide at least BURM_MSGS_MESSAGE_LEN bytes.
262     @param os_errno   Will become the eventual errno related to the message
263     @param severity   Will become the severity related to the message and
264                       should provide at least 80 bytes.
265     @return 1 if a matching item was found, 0 if not, <0 for severe errors
266 */
burn_msgs_obtain(char * minimum_severity,int * error_code,char msg_text[],int * os_errno,char severity[])267 int burn_msgs_obtain(char *minimum_severity,
268                      int *error_code, char msg_text[], int *os_errno,
269                      char severity[])
270 {
271 	int ret, minimum_sevno, sevno, priority;
272 	char *textpt, *sev_name;
273 	struct libdax_msgs_item *item = NULL;
274 
275 	ret = libdax_msgs__text_to_sev(minimum_severity, &minimum_sevno, 0);
276 	if (ret <= 0)
277 		return 0;
278 	if (libdax_messenger == NULL)
279 		return 0;
280 	ret = libdax_msgs_obtain(libdax_messenger, &item, minimum_sevno,
281 				LIBDAX_MSGS_PRIO_ZERO, 0);
282 	if (ret <= 0)
283 		goto ex;
284 	ret = libdax_msgs_item_get_msg(item, error_code, &textpt, os_errno, 0);
285 	if (ret <= 0)
286 		goto ex;
287 	strncpy(msg_text, textpt, BURM_MSGS_MESSAGE_LEN-1);
288 	if(strlen(textpt) >= BURM_MSGS_MESSAGE_LEN)
289 		msg_text[BURM_MSGS_MESSAGE_LEN-1] = 0;
290 
291 	severity[0]= 0;
292 	ret = libdax_msgs_item_get_rank(item, &sevno, &priority, 0);
293 	if(ret <= 0)
294 		goto ex;
295 	ret = libdax_msgs__sev_to_text(sevno, &sev_name, 0);
296 	if(ret <= 0)
297 		goto ex;
298 	strcpy(severity,sev_name);
299 
300 	ret = 1;
301 ex:
302 	libdax_msgs_destroy_item(libdax_messenger, &item, 0);
303 	return ret;
304 }
305 
306 
307 /* ts A70922 : API */
burn_msgs_submit(int error_code,char msg_text[],int os_errno,char severity[],struct burn_drive * d)308 int burn_msgs_submit(int error_code, char msg_text[], int os_errno,
309 			char severity[], struct burn_drive *d)
310 {
311 	int ret, sevno, global_index = -1;
312 
313 	ret = libdax_msgs__text_to_sev(severity, &sevno, 0);
314 	if (ret <= 0)
315 		sevno = LIBDAX_MSGS_SEV_ALL;
316 	if (error_code <= 0) {
317 		switch(sevno) {
318 		       case LIBDAX_MSGS_SEV_ABORT:   error_code = 0x00040000;
319 		break; case LIBDAX_MSGS_SEV_FATAL:   error_code = 0x00040001;
320 		break; case LIBDAX_MSGS_SEV_SORRY:   error_code = 0x00040002;
321 		break; case LIBDAX_MSGS_SEV_WARNING: error_code = 0x00040003;
322 		break; case LIBDAX_MSGS_SEV_HINT:    error_code = 0x00040004;
323 		break; case LIBDAX_MSGS_SEV_NOTE:    error_code = 0x00040005;
324 		break; case LIBDAX_MSGS_SEV_UPDATE:  error_code = 0x00040006;
325 		break; case LIBDAX_MSGS_SEV_DEBUG:   error_code = 0x00040007;
326 		break; default:                      error_code = 0x00040008;
327 		}
328 	}
329 	if (d != NULL)
330 		global_index = d->global_index;
331 	ret = libdax_msgs_submit(libdax_messenger, global_index, error_code,
332 			sevno, LIBDAX_MSGS_PRIO_HIGH, msg_text, os_errno, 0);
333 	return ret;
334 }
335 
336 
337 /* ts A71016 API */
burn_text_to_sev(char * severity_name,int * sevno,int flag)338 int burn_text_to_sev(char *severity_name, int *sevno, int flag)
339 {
340 	int ret;
341 
342 	ret = libdax_msgs__text_to_sev(severity_name, sevno, 0);
343 	return ret;
344 }
345 
346 
347 /* ts A80202 API */
burn_sev_to_text(int severity_number,char ** severity_name,int flag)348 int burn_sev_to_text(int severity_number, char **severity_name, int flag)
349 {
350 	int ret;
351 
352 	ret = libdax_msgs__sev_to_text(severity_number, severity_name, 0);
353 	return ret;
354 }
355 
356 
357 /* ts B21214 API */
burn_list_sev_texts(int flag)358 char *burn_list_sev_texts(int flag)
359 {
360  char *sev_list;
361 
362  libdax_msgs__sev_to_text(0, &sev_list, 1);
363  return sev_list;
364 }
365 
366 
367 /* ts B00224 */
burn_util_thread_id(pid_t pid,pthread_t tid,char text[80])368 char *burn_util_thread_id(pid_t pid, pthread_t tid, char text[80])
369 {
370 	int i, l;
371 
372 	sprintf(text, "[%lu,", (unsigned long int) getpid());
373 	l= strlen(text);
374 	for(i= 0; i < ((int) sizeof(pthread_t)) && 2 * i < 80 - l - 3; i++)
375 		sprintf(text + l + 2 * i,
376 			 "%2.2X", ((unsigned char *) &tid)[i]);
377 
378 	sprintf(text + l + 2 * i, "]");
379 	return text;
380 }
381 
382 
383 /* ts B20122 */
384 /* @param value 0=return rather than exit(value)
385 */
burn_abort_exit(int value)386 int burn_abort_exit(int value)
387 {
388 	burn_abort(4440, burn_abort_pacifier, abort_message_prefix);
389 	fprintf(stderr,
390 	"\n%sABORT : Program done. Even if you do not see a shell prompt.\n\n",
391 		abort_message_prefix);
392 	if (value)
393 		exit(value);
394 	burn_global_abort_level = -2;
395 	return(1);
396 }
397 
398 
burn_builtin_abort_handler(void * handle,int signum,int flag)399 int burn_builtin_abort_handler(void *handle, int signum, int flag)
400 {
401 
402 #define Libburn_new_thread_signal_handleR 1
403 /*
404 #define Libburn_signal_handler_verbouS 1
405 */
406 
407 	int ret;
408 	struct burn_drive *d;
409 
410 #ifdef Libburn_signal_handler_verbouS
411 	char text[80];
412 
413 	fprintf(stderr, "libburn_ABORT: in = %s\n",
414 		burn_util_thread_id(getpid(), pthread_self(), text));
415 	fprintf(stderr, "libburn_ABORT: ctrl = %s\n",
416 		burn_util_thread_id(abort_control_pid, abort_control_thread,
417 					text));
418 	if (burn_global_signal_handler == burn_builtin_abort_handler)
419 		fprintf(stderr, "libburn_ABORT: signal action = %d\n",
420 				burn_builtin_signal_action);
421 
422 	/* >>> find writing drives and report their tid
423 	fprintf(stderr, "libburn_ABORT: wrt = %s\n",
424 		burn_util_thread_id(0, burn_write_thread_id, text));
425 	fprintf(stderr, "libburn_ABORT: sig= %d\n", signum);
426 	*/
427 #endif
428 
429 	burn_builtin_triggered_action = burn_builtin_signal_action;
430 	burn_global_abort_level = -1;
431 
432 	if (burn_builtin_signal_action > 1) {
433 		Cleanup_set_handlers(NULL, NULL, 2);
434 		if (burn_builtin_signal_action == 4)
435 			return -2;
436 		fprintf(stderr,"%sABORT : Trying to shut down busy drives\n",
437 			abort_message_prefix);
438 		fprintf(stderr,
439 		 "%sABORT : Wait the normal burning time before any kill -9\n",
440 		 	abort_message_prefix);
441 		burn_abort_5(0, burn_abort_pacifier, abort_message_prefix,
442 				0, 1);
443 		libdax_msgs_submit(libdax_messenger, -1, 0x00020177,
444 			LIBDAX_MSGS_SEV_ABORT, LIBDAX_MSGS_PRIO_HIGH,
445 			"Urged drive worker threads to do emergency halt",
446 			0, 0);
447 		return -2;
448 	}
449 
450 
451 	/* ---- old deprecated stuck-in-abort-handler loop ---- */
452 
453 	/* ts A70928:
454 	Must be quick. Allowed to coincide with other thread and to share
455 	the increment with that one. It must not decrease, though, and
456 	yield at least 1 if any thread calls this function.
457 	*/
458 	burn_global_abort_level++;
459 	burn_global_abort_signum= signum;
460 
461 	if(getpid() != abort_control_pid) {
462 
463 #ifdef Libburn_new_thread_signal_handleR
464 
465 		ret = burn_drive_find_by_thread_pid(&d, getpid(),
466 							pthread_self());
467 		if (ret > 0 && d->busy == BURN_DRIVE_WRITING) {
468 					/* This is an active writer thread */
469 
470 #ifdef Libburn_signal_handler_verbouS
471 			fprintf(stderr, "libburn_ABORT: pid %d found drive busy with writing, (level= %d)\n", (int) getpid(), burn_global_abort_level);
472 #endif
473 
474 			d->sync_cache(d);
475 
476 			/* >>> perform a more qualified end of burn process */;
477 
478 			d->busy = BURN_DRIVE_IDLE;
479 
480 			if (burn_global_abort_level > 0) {
481 				/* control process did not show up yet */
482 #ifdef Libburn_signal_handler_verbouS
483 					fprintf(stderr, "libburn_ABORT: pid %d sending signum %d to pid %d\n", (int) getpid(), (int) signum, (int) abort_control_pid);
484 #endif
485 					kill(abort_control_pid, signum);
486 			}
487 
488 #ifdef Libburn_signal_handler_verbouS
489 					fprintf(stderr, "libburn_ABORT: pid %d signum %d returning -2\n", (int) getpid(), (int) signum);
490 #endif
491 
492 			return -2;
493 		} else {
494 			usleep(1000000); /* calm down */
495 			return -2;
496 		}
497 
498 #else
499 		usleep(1000000); /* calm down */
500 		return -2;
501 #endif /* ! Libburn_new_thread_signal_handleR */
502 
503 	}
504 	burn_global_abort_level = -1;
505 	Cleanup_set_handlers(NULL, NULL, 2);
506 
507 	fprintf(stderr,"%sABORT : Trying to shut down drive and library\n",
508 		abort_message_prefix);
509 	fprintf(stderr,
510 		"%sABORT : Wait the normal burning time before any kill -9\n",
511 		abort_message_prefix);
512 	close(0); /* somehow stdin as input blocks abort until EOF */
513 
514 	burn_abort_exit(0);
515 	return (1);
516 }
517 
518 
519 /* ts A61002 : API */
burn_set_signal_handling(void * handle,burn_abort_handler_t handler,int mode)520 void burn_set_signal_handling(void *handle, burn_abort_handler_t handler,
521 				int mode)
522 {
523 
524 /*
525 	fprintf(stderr, "libburn_experimental: burn_set_signal_handling, handler==%lx  mode=%d\n", (unsigned long) handler, mode);
526 */
527 
528 	if(handler == NULL) {
529 		handler = burn_builtin_abort_handler;
530 /*
531 		if ((mode & ~4) == 0)
532 			fprintf(stderr, "libburn_experimental: activated burn_builtin_abort_handler() with handle '%s'\n",(handle==NULL ? "libburn : " : (char *) handle));
533 */
534 
535 	}
536 	strcpy(abort_message_prefix, "libburn : ");
537 	abort_message_prefix[0] = 0;
538 	if(handle != NULL && handler == burn_builtin_abort_handler)
539 		strncpy(abort_message_prefix, (char *) handle,
540 			sizeof(abort_message_prefix)-1);
541 	abort_message_prefix[sizeof(abort_message_prefix)-1] = 0;
542 	abort_control_pid = getpid();
543 	abort_control_thread = pthread_self();
544 	burn_builtin_signal_action = (mode >> 4) & 15;
545 	if((mode & 11) != 0)
546 		burn_builtin_signal_action = 0;
547 	if(burn_builtin_signal_action > 1)
548 		burn_builtin_triggered_action = 0;
549 	if(burn_builtin_signal_action == 0)
550 		burn_builtin_signal_action = 1;
551 	Cleanup_set_handlers(handle, (Cleanup_app_handler_T) handler,
552 				 (mode & 15) | 4 | (mode & 256));
553 	burn_global_signal_handle = handle;
554 	burn_global_signal_handler = handler;
555 }
556 
557 
558 /* ts B00304 : API */
burn_is_aborting(int flag)559 int burn_is_aborting(int flag)
560 {
561 	return burn_builtin_triggered_action;
562 }
563 
564 
565 /* ts B00225 */
566 /* @return 0= no abort action 2 pending , 1= not control thread
567 */
burn_init_catch_on_abort(int flag)568 int burn_init_catch_on_abort(int flag)
569 {
570 	if (burn_builtin_triggered_action != 2)
571 		return 0;
572 	if (abort_control_pid != getpid() ||
573 		abort_control_thread != pthread_self())
574 		return 1;
575 	burn_abort(4440, burn_abort_pacifier, abort_message_prefix);
576 	fprintf(stderr,
577 	"\n%sABORT : Program done. Even if you do not see a shell prompt.\n\n",
578 		abort_message_prefix);
579 	exit(1);
580 }
581 
582 
583 /* B20122 */
584 /* Temporarily disable builtin actions 0,1,2 to avoid that burn_abort()
585    waits for its own thread to end grabbing.
586 */
burn_grab_prepare_sig_action(int * signal_action_mem,int flag)587 int burn_grab_prepare_sig_action(int *signal_action_mem, int flag)
588 {
589 	*signal_action_mem = -1;
590 	if (burn_global_signal_handler == burn_builtin_abort_handler &&
591 	    burn_builtin_signal_action >= 0 &&
592 	    burn_builtin_signal_action <= 2) {
593 		*signal_action_mem = burn_builtin_signal_action;
594 		burn_builtin_signal_action = 3;
595 	}
596 	return 1;
597 }
598 
599 
600 /* B20122 */
601 /* Re-enable builtin actions 0,1,2 and perform delayed signal reactions
602 */
burn_grab_restore_sig_action(int signal_action_mem,int flag)603 int burn_grab_restore_sig_action(int signal_action_mem, int flag)
604 {
605 	if (signal_action_mem >= 0)
606 		burn_builtin_signal_action = signal_action_mem;
607 	if (burn_is_aborting(0) && signal_action_mem >= 0) {
608 		if (signal_action_mem == 0 || signal_action_mem == 1) {
609 			burn_abort_exit(1); /* Never comes back */
610 		} else if (signal_action_mem == 2) {
611 			burn_builtin_triggered_action = signal_action_mem;
612 		}
613 	}
614 	return 1;
615 }
616 
617 
618 /* ts A70223 : API */
burn_allow_untested_profiles(int yes)619 void burn_allow_untested_profiles(int yes)
620 {
621 	burn_support_untested_profiles = !!yes;
622 }
623 
624 
625 /* ts A70915 : API */
burn_set_messenger(void * messenger)626 int burn_set_messenger(void *messenger)
627 {
628 	struct libdax_msgs *pt;
629 
630 	if (libdax_msgs_refer(&pt, messenger, 0) <= 0)
631 		return 0;
632 	libdax_msgs_destroy(&libdax_messenger, 0);
633 	libdax_messenger = (struct libdax_msgs *) pt;
634 	return 1;
635 }
636 
637 
638 /* ts A91111 API */
burn_set_scsi_logging(int flag)639 void burn_set_scsi_logging(int flag)
640 {
641 	burn_sg_log_scsi = flag & 7;
642 }
643 
644 
645 /* ts B10312 API */
burn_allow_drive_role_4(int allowed)646 void burn_allow_drive_role_4(int allowed)
647 {
648 	burn_drive_role_4_allowed = (allowed & 0xf);
649 }
650 
651 
652 /* ts B10606 */
burn_alloc_mem(size_t size,size_t count,int flag)653 void *burn_alloc_mem(size_t size, size_t count, int flag)
654 {
655 	void *pt;
656 
657 	pt = calloc(count, size);
658 	if(pt == NULL)
659 		libdax_msgs_submit(libdax_messenger, -1, 0x00000003,
660 				LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
661 				"Out of virtual memory", 0, 0);
662 	return pt;
663 }
664 
665