VirtualBox

source: vbox/trunk/src/VBox/Main/src-server/SerialPortImpl.cpp@ 86506

Last change on this file since 86506 was 82968, checked in by vboxsync, 4 years ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 19.9 KB
Line 
1/* $Id: SerialPortImpl.cpp 82968 2020-02-04 10:35:17Z vboxsync $ */
2/** @file
3 * VirtualBox COM class implementation
4 */
5
6/*
7 * Copyright (C) 2006-2020 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18#define LOG_GROUP LOG_GROUP_MAIN_SERIALPORT
19#include "SerialPortImpl.h"
20#include "MachineImpl.h"
21#include "VirtualBoxImpl.h"
22#include "GuestOSTypeImpl.h"
23
24#include <iprt/assert.h>
25#include <iprt/string.h>
26#include <iprt/cpp/utils.h>
27
28#include <VBox/settings.h>
29
30#include "AutoStateDep.h"
31#include "AutoCaller.h"
32#include "LoggingNew.h"
33
34//////////////////////////////////////////////////////////////////////////////////
35//
36// SerialPort private data definition
37//
38//////////////////////////////////////////////////////////////////////////////////
39
40struct SerialPort::Data
41{
42 Data()
43 : fModified(false),
44 pMachine(NULL)
45 { }
46
47 bool fModified;
48 Machine * const pMachine;
49 const ComObjPtr<SerialPort> pPeer;
50 Backupable<settings::SerialPort> bd;
51};
52
53// constructor / destructor
54/////////////////////////////////////////////////////////////////////////////
55
56DEFINE_EMPTY_CTOR_DTOR(SerialPort)
57
58HRESULT SerialPort::FinalConstruct()
59{
60 return BaseFinalConstruct();
61}
62
63void SerialPort::FinalRelease()
64{
65 uninit();
66 BaseFinalRelease();
67}
68
69// public initializer/uninitializer for internal purposes only
70/////////////////////////////////////////////////////////////////////////////
71
72/**
73 * Initializes the Serial Port object.
74 *
75 * @param aParent Handle of the parent object.
76 * @param aSlot Slot number the serial port is plugged into.
77 */
78HRESULT SerialPort::init(Machine *aParent, ULONG aSlot)
79{
80 LogFlowThisFunc(("aParent=%p, aSlot=%d\n", aParent, aSlot));
81
82 ComAssertRet(aParent, E_INVALIDARG);
83
84 /* Enclose the state transition NotReady->InInit->Ready */
85 AutoInitSpan autoInitSpan(this);
86 AssertReturn(autoInitSpan.isOk(), E_FAIL);
87
88 m = new Data();
89
90 unconst(m->pMachine) = aParent;
91 /* m->pPeer is left null */
92
93 m->bd.allocate();
94
95 /* initialize data */
96 m->bd->ulSlot = aSlot;
97
98 /* Confirm a successful initialization */
99 autoInitSpan.setSucceeded();
100
101 return S_OK;
102}
103
104/**
105 * Initializes the Serial Port object given another serial port object
106 * (a kind of copy constructor). This object shares data with
107 * the object passed as an argument.
108 *
109 * @note This object must be destroyed before the original object
110 * it shares data with is destroyed.
111 *
112 * @note Locks @a aThat object for reading.
113 */
114HRESULT SerialPort::init(Machine *aParent, SerialPort *aThat)
115{
116 LogFlowThisFunc(("aParent=%p, aThat=%p\n", aParent, aThat));
117
118 ComAssertRet(aParent && aThat, E_INVALIDARG);
119
120 /* Enclose the state transition NotReady->InInit->Ready */
121 AutoInitSpan autoInitSpan(this);
122 AssertReturn(autoInitSpan.isOk(), E_FAIL);
123
124 m = new Data();
125
126 unconst(m->pMachine) = aParent;
127 unconst(m->pPeer) = aThat;
128
129 AutoCaller thatCaller(aThat);
130 AssertComRCReturnRC(thatCaller.rc());
131
132 AutoReadLock thatLock(aThat COMMA_LOCKVAL_SRC_POS);
133 m->bd.share(aThat->m->bd);
134
135 /* Confirm a successful initialization */
136 autoInitSpan.setSucceeded();
137
138 return S_OK;
139}
140
141/**
142 * Initializes the guest object given another guest object
143 * (a kind of copy constructor). This object makes a private copy of data
144 * of the original object passed as an argument.
145 *
146 * @note Locks @a aThat object for reading.
147 */
148HRESULT SerialPort::initCopy(Machine *aParent, SerialPort *aThat)
149{
150 LogFlowThisFunc(("aParent=%p, aThat=%p\n", aParent, aThat));
151
152 ComAssertRet(aParent && aThat, E_INVALIDARG);
153
154 /* Enclose the state transition NotReady->InInit->Ready */
155 AutoInitSpan autoInitSpan(this);
156 AssertReturn(autoInitSpan.isOk(), E_FAIL);
157
158 m = new Data();
159
160 unconst(m->pMachine) = aParent;
161 /* pPeer is left null */
162
163 AutoCaller thatCaller(aThat);
164 AssertComRCReturnRC(thatCaller.rc());
165
166 AutoReadLock thatLock(aThat COMMA_LOCKVAL_SRC_POS);
167 m->bd.attachCopy(aThat->m->bd);
168
169 /* Confirm a successful initialization */
170 autoInitSpan.setSucceeded();
171
172 return S_OK;
173}
174
175/**
176 * Uninitializes the instance and sets the ready flag to FALSE.
177 * Called either from FinalRelease() or by the parent when it gets destroyed.
178 */
179void SerialPort::uninit()
180{
181 LogFlowThisFunc(("\n"));
182
183 /* Enclose the state transition Ready->InUninit->NotReady */
184 AutoUninitSpan autoUninitSpan(this);
185 if (autoUninitSpan.uninitDone())
186 return;
187
188 m->bd.free();
189
190 unconst(m->pPeer) = NULL;
191 unconst(m->pMachine) = NULL;
192
193 delete m;
194 m = NULL;
195}
196
197// ISerialPort properties
198/////////////////////////////////////////////////////////////////////////////
199
200HRESULT SerialPort::getEnabled(BOOL *aEnabled)
201{
202 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
203
204 *aEnabled = m->bd->fEnabled;
205
206 return S_OK;
207}
208
209
210HRESULT SerialPort::setEnabled(BOOL aEnabled)
211{
212 LogFlowThisFunc(("aEnabled=%RTbool\n", aEnabled));
213
214 /* the machine needs to be mutable */
215 AutoMutableStateDependency adep(m->pMachine);
216 if (FAILED(adep.rc())) return adep.rc();
217
218 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
219
220 if (m->bd->fEnabled != RT_BOOL(aEnabled))
221 {
222 m->bd.backup();
223 m->bd->fEnabled = RT_BOOL(aEnabled);
224
225 m->fModified = true;
226 // leave the lock before informing callbacks
227 alock.release();
228
229 AutoWriteLock mlock(m->pMachine COMMA_LOCKVAL_SRC_POS);
230 m->pMachine->i_setModified(Machine::IsModified_SerialPorts);
231 mlock.release();
232
233 m->pMachine->i_onSerialPortChange(this);
234 }
235
236 return S_OK;
237}
238
239
240HRESULT SerialPort::getHostMode(PortMode_T *aHostMode)
241{
242 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
243
244 *aHostMode = m->bd->portMode;
245
246 return S_OK;
247}
248
249HRESULT SerialPort::setHostMode(PortMode_T aHostMode)
250{
251 /* the machine needs to be mutable */
252 AutoMutableOrSavedOrRunningStateDependency adep(m->pMachine);
253 if (FAILED(adep.rc())) return adep.rc();
254
255 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
256
257 if (m->bd->portMode != aHostMode)
258 {
259 switch (aHostMode)
260 {
261 case PortMode_RawFile:
262 if (m->bd->strPath.isEmpty())
263 return setError(E_INVALIDARG,
264 tr("Cannot set the raw file mode of the serial port %d "
265 "because the file path is empty or null"),
266 m->bd->ulSlot);
267 break;
268 case PortMode_HostPipe:
269 if (m->bd->strPath.isEmpty())
270 return setError(E_INVALIDARG,
271 tr("Cannot set the host pipe mode of the serial port %d "
272 "because the pipe path is empty or null"),
273 m->bd->ulSlot);
274 break;
275 case PortMode_HostDevice:
276 if (m->bd->strPath.isEmpty())
277 return setError(E_INVALIDARG,
278 tr("Cannot set the host device mode of the serial port %d "
279 "because the device path is empty or null"),
280 m->bd->ulSlot);
281 break;
282 case PortMode_TCP:
283 if (m->bd->strPath.isEmpty())
284 return setError(E_INVALIDARG,
285 tr("Cannot set the host device mode of the serial port %d "
286 "because the server address or TCP port is invalid"),
287 m->bd->ulSlot);
288 break;
289 case PortMode_Disconnected:
290 break;
291#ifdef VBOX_WITH_XPCOM_CPP_ENUM_HACK
292 case PortMode_32BitHack: /* (compiler warnings) */
293 AssertFailedBreak();
294#endif
295 }
296
297 m->bd.backup();
298 m->bd->portMode = aHostMode;
299
300 m->fModified = true;
301 // leave the lock before informing callbacks
302 alock.release();
303
304 AutoWriteLock mlock(m->pMachine COMMA_LOCKVAL_SRC_POS);
305 m->pMachine->i_setModified(Machine::IsModified_SerialPorts);
306 mlock.release();
307
308 m->pMachine->i_onSerialPortChange(this);
309 }
310
311 return S_OK;
312}
313
314HRESULT SerialPort::getSlot(ULONG *aSlot)
315{
316 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
317
318 *aSlot = m->bd->ulSlot;
319
320 return S_OK;
321}
322
323
324HRESULT SerialPort::getIRQ(ULONG *aIRQ)
325{
326 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
327
328 *aIRQ = m->bd->ulIRQ;
329
330 return S_OK;
331}
332
333
334HRESULT SerialPort::setIRQ(ULONG aIRQ)
335{
336 /* check IRQ limits
337 * (when changing this, make sure it corresponds to XML schema */
338 if (aIRQ > 255)
339 return setError(E_INVALIDARG,
340 tr("Invalid IRQ number of the serial port %d: %lu (must be in range [0, %lu])"),
341 m->bd->ulSlot, aIRQ, 255);
342
343 /* the machine needs to be mutable */
344 AutoMutableStateDependency adep(m->pMachine);
345 if (FAILED(adep.rc())) return adep.rc();
346
347 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
348
349 if (m->bd->ulIRQ != aIRQ)
350 {
351 m->bd.backup();
352 m->bd->ulIRQ = aIRQ;
353
354 m->fModified = true;
355 // leave the lock before informing callbacks
356 alock.release();
357
358 AutoWriteLock mlock(m->pMachine COMMA_LOCKVAL_SRC_POS);
359 m->pMachine->i_setModified(Machine::IsModified_SerialPorts);
360 mlock.release();
361
362 m->pMachine->i_onSerialPortChange(this);
363 }
364
365 return S_OK;
366}
367
368
369HRESULT SerialPort::getIOBase(ULONG *aIOBase)
370{
371 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
372
373 *aIOBase = m->bd->ulIOBase;
374
375 return S_OK;
376}
377
378HRESULT SerialPort::setIOBase(ULONG aIOBase)
379{
380 /* check IOBase limits
381 * (when changing this, make sure it corresponds to XML schema */
382 if (aIOBase > 0xFFFF)
383 return setError(E_INVALIDARG,
384 tr("Invalid I/O port base address of the serial port %d: %lu (must be in range [0, 0x%X])"),
385 m->bd->ulSlot, aIOBase, 0, 0xFFFF);
386
387 AutoCaller autoCaller(this);
388 if (FAILED(autoCaller.rc())) return autoCaller.rc();
389
390 /* the machine needs to be mutable */
391 AutoMutableStateDependency adep(m->pMachine);
392 if (FAILED(adep.rc())) return adep.rc();
393
394 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
395
396 HRESULT rc = S_OK;
397
398 if (m->bd->ulIOBase != aIOBase)
399 {
400 m->bd.backup();
401 m->bd->ulIOBase = aIOBase;
402
403 m->fModified = true;
404 // leave the lock before informing callbacks
405 alock.release();
406
407 AutoWriteLock mlock(m->pMachine COMMA_LOCKVAL_SRC_POS);
408 m->pMachine->i_setModified(Machine::IsModified_SerialPorts);
409 mlock.release();
410
411 m->pMachine->i_onSerialPortChange(this);
412 }
413
414 return rc;
415}
416
417HRESULT SerialPort::getPath(com::Utf8Str &aPath)
418{
419 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
420
421 aPath = m->bd->strPath;
422
423 return S_OK;
424}
425
426
427HRESULT SerialPort::setPath(const com::Utf8Str &aPath)
428{
429 /* the machine needs to be mutable */
430 AutoMutableOrSavedOrRunningStateDependency adep(m->pMachine);
431 if (FAILED(adep.rc())) return adep.rc();
432
433 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
434
435 if (aPath != m->bd->strPath)
436 {
437 HRESULT rc = i_checkSetPath(aPath);
438 if (FAILED(rc)) return rc;
439
440 m->bd.backup();
441 m->bd->strPath = aPath;
442
443 m->fModified = true;
444 // leave the lock before informing callbacks
445 alock.release();
446
447 AutoWriteLock mlock(m->pMachine COMMA_LOCKVAL_SRC_POS);
448 m->pMachine->i_setModified(Machine::IsModified_SerialPorts);
449 mlock.release();
450
451 m->pMachine->i_onSerialPortChange(this);
452 }
453
454 return S_OK;
455}
456
457HRESULT SerialPort::getServer(BOOL *aServer)
458{
459 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
460
461 *aServer = m->bd->fServer;
462
463 return S_OK;
464}
465
466HRESULT SerialPort::setServer(BOOL aServer)
467{
468 /* the machine needs to be mutable */
469 AutoMutableOrSavedOrRunningStateDependency adep(m->pMachine);
470 if (FAILED(adep.rc())) return adep.rc();
471
472 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
473
474 if (m->bd->fServer != RT_BOOL(aServer))
475 {
476 m->bd.backup();
477 m->bd->fServer = RT_BOOL(aServer);
478
479 m->fModified = true;
480 // leave the lock before informing callbacks
481 alock.release();
482
483 AutoWriteLock mlock(m->pMachine COMMA_LOCKVAL_SRC_POS);
484 m->pMachine->i_setModified(Machine::IsModified_SerialPorts);
485 mlock.release();
486
487 m->pMachine->i_onSerialPortChange(this);
488 }
489
490 return S_OK;
491}
492
493HRESULT SerialPort::getUartType(UartType_T *aUartType)
494{
495 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
496
497 *aUartType = m->bd->uartType;
498
499 return S_OK;
500}
501
502HRESULT SerialPort::setUartType(UartType_T aUartType)
503{
504 /* the machine needs to be mutable */
505 AutoMutableOrSavedOrRunningStateDependency adep(m->pMachine);
506 if (FAILED(adep.rc())) return adep.rc();
507
508 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
509
510 if (m->bd->uartType != aUartType)
511 {
512 m->bd.backup();
513 m->bd->uartType = aUartType;
514
515 m->fModified = true;
516 // leave the lock before informing callbacks
517 alock.release();
518
519 AutoWriteLock mlock(m->pMachine COMMA_LOCKVAL_SRC_POS);
520 m->pMachine->i_setModified(Machine::IsModified_SerialPorts);
521 mlock.release();
522
523 m->pMachine->i_onSerialPortChange(this);
524 }
525
526 return S_OK;
527}
528
529// public methods only for internal purposes
530////////////////////////////////////////////////////////////////////////////////
531
532/**
533 * Loads settings from the given port node.
534 * May be called once right after this object creation.
535 *
536 * @param data Configuration settings.
537 *
538 * @note Locks this object for writing.
539 */
540HRESULT SerialPort::i_loadSettings(const settings::SerialPort &data)
541{
542
543 AutoCaller autoCaller(this);
544 AssertComRCReturnRC(autoCaller.rc());
545
546 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
547
548 // simply copy
549 *m->bd.data() = data;
550
551 return S_OK;
552}
553
554/**
555 * Saves the port settings to the given port node.
556 *
557 * Note that the given Port node is completely empty on input.
558 *
559 * @param data Configuration settings.
560 *
561 * @note Locks this object for reading.
562 */
563HRESULT SerialPort::i_saveSettings(settings::SerialPort &data)
564{
565 AutoCaller autoCaller(this);
566 AssertComRCReturnRC(autoCaller.rc());
567
568 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
569
570 // simply copy
571 data = *m->bd.data();
572
573 return S_OK;
574}
575
576/**
577 * Returns true if any setter method has modified settings of this instance.
578 * @return
579 */
580bool SerialPort::i_isModified()
581{
582 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
583 return m->fModified;
584}
585
586/**
587 * @note Locks this object for writing.
588 */
589void SerialPort::i_rollback()
590{
591 /* sanity */
592 AutoCaller autoCaller(this);
593 AssertComRCReturnVoid(autoCaller.rc());
594
595 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
596
597 m->bd.rollback();
598}
599
600/**
601 * @note Locks this object for writing, together with the peer object (also
602 * for writing) if there is one.
603 */
604void SerialPort::i_commit()
605{
606 /* sanity */
607 AutoCaller autoCaller(this);
608 AssertComRCReturnVoid(autoCaller.rc());
609
610 /* sanity too */
611 AutoCaller peerCaller(m->pPeer);
612 AssertComRCReturnVoid(peerCaller.rc());
613
614 /* lock both for writing since we modify both (pPeer is "master" so locked
615 * first) */
616 AutoMultiWriteLock2 alock(m->pPeer, this COMMA_LOCKVAL_SRC_POS);
617
618 if (m->bd.isBackedUp())
619 {
620 m->bd.commit();
621 if (m->pPeer)
622 {
623 /* attach new data to the peer and reshare it */
624 m->pPeer->m->bd.attach(m->bd);
625 }
626 }
627}
628
629/**
630 * @note Locks this object for writing, together with the peer object
631 * represented by @a aThat (locked for reading).
632 */
633void SerialPort::i_copyFrom(SerialPort *aThat)
634{
635 AssertReturnVoid(aThat != NULL);
636
637 /* sanity */
638 AutoCaller autoCaller(this);
639 AssertComRCReturnVoid(autoCaller.rc());
640
641 /* sanity too */
642 AutoCaller thatCaller(aThat);
643 AssertComRCReturnVoid(thatCaller.rc());
644
645 /* peer is not modified, lock it for reading (aThat is "master" so locked
646 * first) */
647 AutoReadLock rl(aThat COMMA_LOCKVAL_SRC_POS);
648 AutoWriteLock wl(this COMMA_LOCKVAL_SRC_POS);
649
650 /* this will back up current data */
651 m->bd.assignCopy(aThat->m->bd);
652}
653
654/**
655 * Applies the defaults for this serial port.
656 *
657 * @note This method currently assumes that the object is in the state after
658 * calling init(), it does not set defaults from an arbitrary state.
659 */
660void SerialPort::i_applyDefaults(GuestOSType *aOsType)
661{
662 /* sanity */
663 AutoCaller autoCaller(this);
664 AssertComRCReturnVoid(autoCaller.rc());
665
666 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
667
668 /* Set some more defaults. */
669 switch (m->bd->ulSlot)
670 {
671 case 0:
672 {
673 m->bd->ulIOBase = 0x3f8;
674 m->bd->ulIRQ = 4;
675 break;
676 }
677 case 1:
678 {
679 m->bd->ulIOBase = 0x2f8;
680 m->bd->ulIRQ = 3;
681 break;
682 }
683 case 2:
684 {
685 m->bd->ulIOBase = 0x3e8;
686 m->bd->ulIRQ = 4;
687 break;
688 }
689 case 3:
690 {
691 m->bd->ulIOBase = 0x2e8;
692 m->bd->ulIRQ = 3;
693 break;
694 }
695 default:
696 AssertMsgFailed(("Serial port slot %u exceeds limit\n", m->bd->ulSlot));
697 break;
698 }
699
700 uint32_t numSerialEnabled = 0;
701 if (aOsType)
702 numSerialEnabled = aOsType->i_numSerialEnabled();
703
704 /* Enable port if requested */
705 if (m->bd->ulSlot < numSerialEnabled)
706 {
707 m->bd->fEnabled = true;
708 }
709}
710
711bool SerialPort::i_hasDefaults()
712{
713 /* sanity */
714 AutoCaller autoCaller(this);
715 AssertComRCReturn(autoCaller.rc(), true);
716
717 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
718
719 if ( !m->bd->fEnabled
720 && m->bd->portMode == PortMode_Disconnected
721 && !m->bd->fServer)
722 {
723 /* Could be default, check the IO base and IRQ. */
724 switch (m->bd->ulSlot)
725 {
726 case 0:
727 if (m->bd->ulIOBase == 0x3f8 && m->bd->ulIRQ == 4)
728 return true;
729 break;
730 case 1:
731 if (m->bd->ulIOBase == 0x2f8 && m->bd->ulIRQ == 3)
732 return true;
733 break;
734 case 2:
735 if (m->bd->ulIOBase == 0x3e8 && m->bd->ulIRQ == 4)
736 return true;
737 break;
738 case 3:
739 if (m->bd->ulIOBase == 0x2e8 && m->bd->ulIRQ == 3)
740 return true;
741 break;
742 default:
743 AssertMsgFailed(("Serial port slot %u exceeds limit\n", m->bd->ulSlot));
744 break;
745 }
746
747 /* Detect old-style defaults (0x3f8, irq 4) in any slot, they are still
748 * in place for many VMs created by old VirtualBox versions. */
749 if (m->bd->ulIOBase == 0x3f8 && m->bd->ulIRQ == 4)
750 return true;
751 }
752
753 return false;
754}
755
756/**
757 * Validates COMSETTER(Path) arguments.
758 */
759HRESULT SerialPort::i_checkSetPath(const Utf8Str &str)
760{
761 AssertReturn(isWriteLockOnCurrentThread(), E_FAIL);
762
763 if ( ( m->bd->portMode == PortMode_HostDevice
764 || m->bd->portMode == PortMode_HostPipe
765 || m->bd->portMode == PortMode_TCP
766 || m->bd->portMode == PortMode_RawFile
767 ) && str.isEmpty()
768 )
769 return setError(E_INVALIDARG,
770 tr("Path of the serial port %d may not be empty or null in "
771 "host pipe, host device or TCP mode"),
772 m->bd->ulSlot);
773
774 return S_OK;
775}
776
777/* vi: set tabstop=4 shiftwidth=4 expandtab: */
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use